#include "dryctrlthread.h"
#include "rtdb.h"
#include  <math.h>

#define SIGNAL_LOG_COUNT 60

//#define EMS_CTRL_SWITCH_CLOSE_STR    "IO控制汇流开关合闸."
//#define EMS_CTRL_SWITCH_OPEN_STR     "IO控制汇流开关分闸."
//#define SERIAL_IO_DEV_CONN_ERROR	"串口继电器通信故障."
//#define SERIAL_IO_DEV_CONN_OK		"串口继电器通信恢复."

//#define SWITCH_CLOSED_STR    		"汇流开关合闸."
//#define SWITCH_OPENED_STR     	"汇流开关分闸."

//unsigned char  g_DIState = 0;// 4路继电器输出4路开关量输入（转发卡） 的DI状态 DI1和DI2闭合时值为3， 只有DI3闭合时值为4
//unsigned char  g_DOState = 0;// 4路继电器输出4路开关量输入（转发卡） 的DO状态 DO1和DO2闭合时值为3， 只有DO3闭合时值为4
//int      g_bReadDiFlag = 0; // 是否已经获取到DI状态
//int      g_bReadDoFlag = 0; // 是否已经获取到DO状态
//quint16  g_connFailedCount = 0; // 通迅故障计时，通迅正常时清0

void DryCtrlThread::sendLog(int iLogType, const QString& strLog)
{
	writeKgLogfile(strLog);
}

DryCtrlThread::DryCtrlThread(QObject *parent)
	: QThread(parent)
{
    m_pIOReader = new IOReader(this, KgGlobalData::ms_comDevName);
	m_fireCount = 0;
	m_fireAlarm = 0;
	m_fireAlarm = 0;
	// m_fireDetectAlarm = 0;
	m_oldFireAlarm = 0;
	m_fireSignal = 0;

	m_fireSprayCount = 0;
	m_fireSpraySignal = 0;
	m_fireSprayAlarm = 0;
	m_oldFireSprayAlarm = 0;

	m_fireFaultCount = 0;
	m_fireFaultAlarm = 0;
	
	m_waterCount = 0;
	m_waterAlarm = 0;
	m_waterSignal = 0;
	
	m_thunderCount = 0;
	m_thunderAlarm = 0;
	m_thunderSignal = 0;

	m_emergStopCount = 0;
	m_emergStopAlarm = 0;
	m_usOldEmerStopState = 0;
	m_emergStopSignal = 0;

	m_waterCountSec = 0;
	m_waterAlarmSec = 0;
	m_waterSignalSec = 0;
	
	m_thunderCountSec = 0;
	m_thunderAlarmSec = 0;
	m_thunderSignalSec = 0;

	m_emergStopCountSec = 0;
	m_emergStopAlarmSec = 0;
	m_emergStopSignalSec = 0;

	m_bmsLocalCount = 0;
	m_bmsLocalSignal = 0;
	m_bmsLocalState = 0;  // 1:BMS就地 0:BMS远方

	m_bmsRemoteCount = 0;
	m_bmsRemoteSignal = 0;
	m_bmsRemoteState = 0;  // 1:BMS远方 0:S就地

	m_combusGasCount = 0;
	m_combusGasAlarm = 0;
	m_combusGasDetectAlarm = 0;
	m_combusGasSignal = 0;

	m_fuseCount = 0;
	m_fuseAlarm = 0;
    m_fuseSignal = 0;

	m_xfMotionCount = 0;
    m_xfMotionAlarm = 0;

	m_fireManuCount = 0;
	m_fireManuMode = 0;

	m_elecPowerOffCount = 0;
	m_elecPowerOffAlarm = 0;

	m_xfWarmCount= 0;
	m_xfWarmMsg= 0;

	m_upsAlarmCount = 0;
	m_upsAlarm= 0;
	
	m_doorAlarmCount = 0;
	m_doorAlarm= 0;

	m_doorAlarmCountSec = 0;
	m_doorAlarmSec = 0;

	m_acFaultCount = 0;
	m_acFault = 0;

	m_lqFaultCount = 0;
	m_lqFault = 0;
	m_stackState = 0;                // 当前堆状态
	m_statChangeTime = QDateTime();  // 堆状态改变时间
	
	m_sendHzCount = 0;
    m_hzSucced = 0;
	
	//m_hlkgState = 99;
	for(int i = 0; i < MAX_HLKG_COUNT; ++i)
	{
		m_hlkgState[i] = 99;
	}

	for(int i = 0; i < MAX_GLKG_COUNT; ++i)
	{
		m_glkgState[i] = 99;
	}

	m_drvFzCount = 0;   // 已发送分闸/脱扣命令记数
	m_drvFzSuccedCount = 0;
	//drvFzTime;      // 最近一次驱动分闸时间

	m_drvHzCount = 0;   // 已发送合闸命令记数
	m_drvHzSuccedCount = 0;
	
	m_oldConnState = 0; // 并网连接状态 

	m_masterFzCount = 0;// 主动分闸记数
	m_masterHzCount = 0;// 主动合闸记数

	m_saveEmsCtrlHzRdCount = 0;// 保存EMS控制汇流开关记录后计时
	m_saveEmsCtrlFzRdCount = 0;
	m_saveRejectEmsHzRdCount = 0;

	m_detectYcCount = 0;
	m_detectOkCount = 0;

	//m_setDoCount = 0;

	m_usOldHasAlarm = 0;
	m_usOldHasProt = 0;

	m_usConnFailed = 99; // 是否有通迅故障 0:无 1:有, 99:没有初始化

	m_usOldChgJcqState = 99; 
	m_usOldDchgJcqState = 99; 

	//m_iLogCount = 0;
	
	m_xfTkMotionCount = 0;
	m_xfTkMotionLogCount = 0;

	m_xfSprayTkMotionCount = 0;
	m_xfSprayTkMotionLogCount = 0;
	
	m_volDownProtTkCount = 0;
	m_volDownProtTkLogCount = 0;

	m_signalLogCount = 0;

	m_isolSwitchClosedCount = 0;
	m_isolSwitchOpendCount = 0; 

	for(int i = 0; i < 10; ++i)
	{
		m_reservedAlarm[i] = 0;
		m_reservedCount[i] = 0;
	}

	m_mainSwitchCount = 0; 
	m_mainSwitchClosed = 0; 
}

DryCtrlThread::~DryCtrlThread()
{

}

// 判断对应的干结点是否发生告警 added 2021-2-22
// bool HasAlarmVal(XFStrategy stg, unsigned char dIState, int type, QString &strPos) // modifed 2023-3-13
bool HasAlarmVal(XFStrategy stg, int dIState, int type, QString &strPos)
{
     bool bAlarm = false;
	 for(int i = 0; i < stg.diList.size(); ++i)
	 {
	 	DI_STU diStu = stg.diList[i];
		int xfMask = 1 << diStu.diIndex;
		 //printf("dIState==========%d\n", dIState);
		 if (1 == diStu.alarmValue) // 常开干结点
		 {
			 if (xfMask == (xfMask & dIState))// 有告警
			 {
			 	bAlarm = true;
				if (strPos.length() > 0)
				{
					strPos +=",";
				}
				strPos += QString("%1").arg(1+diStu.diIndex);
			 }
			 else
			 {
			 	;
			 }
		 }
		 else  // 常闭干结点
		 {
		 	if (xfMask == (xfMask & dIState))
			 {

			 }
			 else // 有告警
			 {
			 	bAlarm = true;
				if (strPos.length() > 0)
				{
					strPos +=",";
				}
				strPos += QString("%1").arg(1+diStu.diIndex);
			 }
		 }
	  }

	 return bAlarm;
}

void DryCtrlThread::judgeXfAlarm()
{
   if (KgGlobalData::ms_xfStrategy.diList.size() > 0) // 有采集消防信号
   {
   	   //int xfMask = 1 << KgGlobalData::ms_xfStrategy.diIndex;
	   //if (xfMask == (xfMask & KgGlobalData::ms_dryData.DIVal))//有消防告警
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_xfStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   //if(++fireCount > 2)     //消防告警维持2个周期（约10秒）才确认
		   if (++m_fireCount >= KgGlobalData::ms_xfStrategy.confirmedCount)
		   {
			   if (0 == m_fireAlarm)
			   {	if(isChLang())
			   		   //saveLogToBaDb(QString("确认发生消防告警(DI%1).").arg(strPos));
			   		   //saveLogToBaDb(QString("确认发生消防告警(DI%1).").arg(strPos));
			   		   saveLogToBaDb(kgConvert("发生消防告警") + QString("(DI%1).").arg(strPos));
			   		   //saveLogToBaDb(QString("确认发生消防2级预警(DI%1).").arg(strPos));//  YW0318
			        else
					   saveLogToBaDb(QString("Confirm fire alarm(DI%1).").arg(strPos));
			   }
			   //if (999 == KgGlobalData::ms_pStack->usFireBankAddr)
		   	   //   m_fireAlarm  = 1;
			   //else
			   //	m_fireDetectAlarm = 1;
			   m_fireAlarm  = 1;
			   sendLog(0, "******************fireAlarm");
		   }
		   else
		   {
		   	   if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_fireSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   //saveLogToBaDb(QString("读取到消防信号(DI%1).").arg(strPos));
			   		   //saveLogToBaDb(QString("读取到消防告警信号(DI%1).").arg(strPos));
			   		   saveLogToBaDb(kgConvert("读取到消防信号") + QString("(DI%1).").arg(strPos));
			   		   //saveLogToBaDb(QString("读取到消防2级预警信号(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read fire signal(DI%1).").arg(strPos));
			   	}
			    m_fireSignal = 1;
		   }
		   
		   if (m_fireCount > 10000)  //防止次数太大溢出
		   {
			   m_fireCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_fireAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("消防告警结束."));
				else
				   saveLogToBaDb(QString("Fire alarm is over."));
		   }

		   m_fireCount = 0;
		   m_fireAlarm = 0;
		   //m_fireDetectAlarm = 0;
		   m_fireSignal = 0;
		   //sendLog(0, "fireAlarm is 0");
	   }
	}
}

void DryCtrlThread::judgeXfSparyAlam() // added 2022-12-10
{
   if (KgGlobalData::ms_xfSprayStrategy.diList.size() > 0) // 有采集消防喷洒信号
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_xfSprayStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   if (++m_fireSprayCount >= KgGlobalData::ms_xfSprayStrategy.confirmedCount)
		   {
			   if (0 == m_fireSprayAlarm)
			   {	if(isChLang())

			   		   saveLogToBaDb(kgConvert("发生消防喷洒") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Confirm fire spray(DI%1).").arg(strPos));
			   }
			   m_fireSprayAlarm  = 1;
			   sendLog(0, "******************fireSprayAlarm");
		   }
		   else
		   {
		   	   if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_fireSpraySignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到消防喷洒信号")         + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read fire spray signal(DI%1).").arg(strPos));
			   	}
			    m_fireSpraySignal = 1;
		   }
		   
		   if (m_fireSprayCount > 10000)  //防止次数太大溢出
		   {
			   m_fireSprayCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_fireSprayAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("消防喷洒结束."));
				else
				   saveLogToBaDb(QString("Fire spray alarm is over."));
		   }

		   m_fireSprayCount = 0;
		   m_fireSprayAlarm = 0;
		   m_fireSpraySignal = 0;
	   }
	}
}

void DryCtrlThread::judgeXfFaultAlam() // added 2022-12-21
{
   if (KgGlobalData::ms_xfFaultStrategy.diList.size() > 0) // 有采集消防故障信号
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_xfFaultStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   if (++m_fireFaultCount >= KgGlobalData::ms_xfFaultStrategy.confirmedCount)
		   {
			   if (0 == m_fireFaultAlarm)
			   {	if(isChLang())

			   		   saveLogToBaDb(kgConvert("发生消防故障") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Confirm fire fault(DI%1).").arg(strPos));
			   }
			   m_fireFaultAlarm  = 1;
			   sendLog(0, "******************fireFaultAlarm");
		   }
		   
		   if (m_fireFaultCount > 10000)  //防止次数太大溢出
		   {
			   m_fireFaultCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_fireFaultAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("消防故障结束."));
				else
				   saveLogToBaDb(QString("Fire fault alarm is over."));
		   }

		   m_fireFaultCount = 0;
		   m_fireFaultAlarm = 0;
	   }
	}
}


void DryCtrlThread::judgeXfAutoManu()  //  27
{
   if (KgGlobalData::ms_xfManuAutoStrategy.diList.size() > 0) 
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_xfManuAutoStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   if (++m_fireManuCount >= KgGlobalData::ms_xfManuAutoStrategy.confirmedCount)
		   {
			   if (0 == m_fireManuMode)
			   {	if(isChLang())

			   		   saveLogToBaDb(kgConvert("消防转为手动") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Xf switch to manu mode(DI%1).").arg(strPos));
			   }
			   m_fireManuMode  = 1;
			   sendLog(0, "******************Xf ManuMode");
		   }
		   
		   if (m_fireManuCount > 10000)  //防止次数太大溢出
		   {
			   m_fireManuCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_fireManuMode)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("消防转为自动."));
				else
				   saveLogToBaDb(QString("Xf switch to auto mode."));
		   }

		   m_fireManuCount = 0;
		   m_fireManuMode = 0;
	   }

	   //KgGlobalData::ms_pStack->aEnvFireFault = m_fireFaultAlarm;
	   //KgGlobalData::ms_pStack->aFireFault = m_fireFaultAlarm;                        // 消防故障
	}
}

void DryCtrlThread::judgeElecPowerOff()  //  27
{
   if (KgGlobalData::ms_elecPowerOffStrategy.diList.size() > 0) 
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_elecPowerOffStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   if (++m_elecPowerOffCount >= KgGlobalData::ms_elecPowerOffStrategy.confirmedCount)
		   {
			   if (0 == m_elecPowerOffAlarm)
			   {	if(isChLang())

			   		   saveLogToBaDb(kgConvert("市电断电") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Elec power off(DI%1).").arg(strPos));
			   }
			   m_elecPowerOffAlarm  = 1;
			   sendLog(0, "******************Elec power off");
		   }
		   
		   if (m_elecPowerOffCount > 10000)  //防止次数太大溢出
		   {
			   m_elecPowerOffCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_elecPowerOffAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("市电恢复正常."));
				else
				   saveLogToBaDb(QString("Elec power normal."));
		   }

		   m_elecPowerOffCount = 0;
		   m_elecPowerOffAlarm = 0;
	   }

	   //KgGlobalData::ms_pStack->aEnvFireFault = m_fireFaultAlarm;
	   //KgGlobalData::ms_pStack->aFireFault = m_fireFaultAlarm;                        // 消防故障
	}
}

void DryCtrlThread::judgeWaterAlarm()
{
   if (KgGlobalData::ms_waterStrategy.diList.size() > 0) // 有采集水浸信号
   {
   	   //int xfMask = 1 << KgGlobalData::ms_waterStrategy.diIndex;
	   //if (xfMask == (xfMask & KgGlobalData::ms_dryData.DIVal))//有水浸告警
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_waterStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   //if(++fireCount > 2)     //水浸告警维持2个周期（约10秒）才确认
		   if (++m_waterCount >= KgGlobalData::ms_waterStrategy.confirmedCount)
		   {
			   if (0 == m_waterAlarm)
			   {	if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生水浸告警") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Confirm water alarm(DI%1).").arg(strPos));
			   }
		   	   m_waterAlarm  = 1;
			   sendLog(0, "******************waterAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_waterSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到水浸信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read water signal(DI%1).").arg(strPos));
			   	}
			    m_waterSignal = 1;
		   }
				
		   if (m_waterCount > 10000)  //防止次数太大溢出
		   {
			   m_waterCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_waterAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("水浸告警结束."));
				else
				   saveLogToBaDb(QString("Water alarm is over."));
		   }
		   m_waterCount = 0;
		   m_waterAlarm = 0;
		   m_waterSignal = 0;
		   //sendLog(0, "waterAlarm is 0");
	   }
	   KgGlobalData::ms_pStack->usStackTemp[30] = m_waterAlarm;// added 2023-5-29
	}
}

void DryCtrlThread::judgeWaterAlarmSec()
{
   if (KgGlobalData::ms_waterStrategySec.diList.size() > 0) // 有采集水浸信号
   {
   	   //int xfMask = 1 << KgGlobalData::ms_waterStrategy.diIndex;
	   //if (xfMask == (xfMask & KgGlobalData::ms_dryData.DIVal))//有水浸告警
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_waterStrategySec, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   //if(++fireCount > 2)     //水浸告警维持2个周期（约10秒）才确认
		   if (++m_waterCountSec >= KgGlobalData::ms_waterStrategySec.confirmedCount)
		   {
			   if (0 == m_waterAlarmSec)
			   {	if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生#2水浸告警") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Confirm #2 Water alarm(DI%1).").arg(strPos));
			   }
		   	   m_waterAlarmSec  = 1;
			   sendLog(0, "******************#2 WaterAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_waterSignalSec && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到#2水浸信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read #2 Water signal(DI%1).").arg(strPos));
			   	}
			    m_waterSignalSec = 1;
		   }
				
		   if (m_waterCountSec > 10000)  //防止次数太大溢出
		   {
			   m_waterCountSec = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_waterAlarmSec)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("#2水浸告警结束."));
				else
				   saveLogToBaDb(QString("#2 Water alarm is over."));
		   }
		   m_waterCountSec = 0;
		   m_waterAlarmSec = 0;
		   m_waterSignalSec = 0;
		   //sendLog(0, "waterAlarm is 0");
	   }
	   //KgGlobalData::ms_pStack->aEnvWaterAlarm[1] = m_waterAlarmSec;
	   //KgGlobalData::ms_pStack->aWaterAlarm = m_waterAlarm;    // 水浸告警  
	}
}

void DryCtrlThread::judgeThunderAlarm()
{
   if (KgGlobalData::ms_tdStrategy.diList.size() > 0)  // 有采集防雷信号
   {
   	   //int tdMask = 1 << KgGlobalData::ms_tdStrategy.diIndex;
	   //if (tdMask == (tdMask & g_DIState))//有防雷信号
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_tdStrategy, KgGlobalData::ms_dryData.DIVal,2,strPos))
	   {
		   //if(++m_thunderCount > 2)     // 防雷告警维持3个周期（约5秒）才确认
		   if(++m_thunderCount >= KgGlobalData::ms_tdStrategy.confirmedCount) 
		   {
		   	   if (0 == m_thunderAlarm)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生雷击告警") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("Confirm thunder alarm(DI%1).").arg(strPos));
			   }
		   	   m_thunderAlarm  = 1;
			   sendLog(0, "******************thunderAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_thunderSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到雷击信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read thunder signal(DI%1).").arg(strPos));
			   	}
			    m_thunderSignal = 1;
		   }
			
		   if (m_thunderCount > 10000)  //防止次数太大溢出
		   {
			   m_thunderCount = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_thunderAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("雷击告警结束."));
				else
				   saveLogToBaDb(QString("Thunder alarm is over."));
		   }
		   m_thunderCount = 0;
		   m_thunderAlarm = 0;
		   m_thunderSignal = 0;
		   //sendLog(0, "thunderAlarm is 0");
	   }
	}
}


void DryCtrlThread::judgeThunderAlarmSec()
{
   if (KgGlobalData::ms_tdStrategySec.diList.size() > 0)  // 有采集防雷信号
   {
   	   //int tdMask = 1 << KgGlobalData::ms_tdStrategy.diIndex;
	   //if (tdMask == (tdMask & g_DIState))//有防雷信号
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_tdStrategySec, KgGlobalData::ms_dryData.DIVal,2,strPos))
	   {
		   //if(++m_thunderCount > 2)     // 防雷告警维持3个周期（约5秒）才确认
		   if(++m_thunderCountSec >= KgGlobalData::ms_tdStrategySec.confirmedCount) 
		   {
		   	   if (0 == m_thunderAlarmSec)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生#2雷击告警") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("Confirm #2 Thunder alarm(DI%1).").arg(strPos));
			   }
		   	   m_thunderAlarmSec  = 1;
			   sendLog(0, "******************#2 ThunderAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_thunderSignalSec && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到#2雷击信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read #2 Thunder signal(DI%1).").arg(strPos));
			   	}
			    m_thunderSignalSec = 1;
		   }
			
		   if (m_thunderCountSec > 10000)  //防止次数太大溢出
		   {
			   m_thunderCountSec = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_thunderAlarmSec)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("#2雷击告警结束."));
				else
				   saveLogToBaDb(QString("#2 Thunder alarm is over."));
		   }
		   m_thunderCountSec = 0;
		   m_thunderAlarmSec = 0;
		   m_thunderSignalSec = 0;
		   //sendLog(0, "thunderAlarm is 0");
	   }
	   //KgGlobalData::ms_pStack->aStackTemp[5] = m_thunderAlarm; 
	   //KgGlobalData::ms_pStack->aEnvTemp[13] = m_thunderAlarmSec;
	}
}

void DryCtrlThread::judgeEmergeStop()
{
   if (KgGlobalData::ms_emgStopStrategy.diList.size() > 0) // 有采集急停信号
   {
   	   //int tdMask = 1 << KgGlobalData::ms_emgStopStrategy.diIndex;
	   //if (tdMask == (tdMask & g_DIState))//有急停信号
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_emgStopStrategy, KgGlobalData::ms_dryData.DIVal,3,strPos))
	   {
		   //if(++m_emergStopCount > 2)     // 急停信号维持3个周期（约5秒）才确认
		   if(++m_emergStopCount  >= KgGlobalData::ms_emgStopStrategy.confirmedCount) 
		   {
		   	   if (0 == m_emergStopAlarm)
			   {	
			       if(isChLang())
			   	      saveLogToBaDb(kgConvert("发生急停") + QString("(DI%1).").arg(strPos));
				   else
				   	  saveLogToBaDb(QString("Confirm emergency stop(DI%1).").arg(strPos));
			   }
		   	   m_emergStopAlarm  = 1;
			   sendLog(0, "******************emergStopAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_emergStopSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到急停信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read emergency signal(DI%1).").arg(strPos));
			   	}
			    m_emergStopSignal = 1;
		   }
		   
		   if (m_emergStopCount > 10000)  //防止次数太大溢出
		   {
			   m_emergStopCount = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_emergStopAlarm)
		   {
		   	   if(isChLang())
		   	      saveLogToBaDb(kgConvert("急停结束."));
			   else
				  saveLogToBaDb(QString("Emergency stop is over."));
		   }
		   m_emergStopCount = 0;
		   m_emergStopAlarm = 0;
		   m_emergStopSignal = 0;
		   //sendLog(0, "emergStopAlarm is 0");
	   }
	}
}


void DryCtrlThread::judgeEmergeStopSec()
{
   if (KgGlobalData::ms_emgStopStrategySec.diList.size() > 0) // 有采集急停信号
   {
   	   //int tdMask = 1 << KgGlobalData::ms_emgStopStrategy.diIndex;
	   //if (tdMask == (tdMask & g_DIState))//有急停信号
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_emgStopStrategySec, KgGlobalData::ms_dryData.DIVal,3,strPos))
	   {
		   //if(++m_emergStopCount > 2)     // 急停信号维持3个周期（约5秒）才确认
		   if(++m_emergStopCountSec  >= KgGlobalData::ms_emgStopStrategySec.confirmedCount) 
		   {
		   	   if (0 == m_emergStopAlarmSec)
			   {	
			       if(isChLang())
			   	      saveLogToBaDb(kgConvert("发生#2急停") + QString("(DI%1).").arg(strPos));
				   else
				   	  saveLogToBaDb(QString("Confirm #2 Emergency stop(DI%1).").arg(strPos));
			   }
		   	   m_emergStopAlarmSec  = 1;
			   sendLog(0, "******************#2 EmergStopAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_emergStopSignalSec && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到#2急停信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read #2 Emergency signal(DI%1).").arg(strPos));
			   	}
			    m_emergStopSignalSec = 1;
		   }
		   
		   if (m_emergStopCountSec > 10000)  //防止次数太大溢出
		   {
			   m_emergStopCountSec = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_emergStopAlarmSec)
		   {
		   	   if(isChLang())
		   	      saveLogToBaDb(kgConvert("#2急停结束."));
			   else
				  saveLogToBaDb(QString("#2 Emergency stop is over."));
		   }
		   m_emergStopCountSec = 0;
		   m_emergStopAlarmSec = 0;
		   m_emergStopSignalSec = 0;
		   //sendLog(0, "emergStopAlarm is 0");
	   }

	   if (m_emergStopAlarmSec) // 发生急停
		{
			//KgGlobalData::ms_pStack->usEmerStopState = 1;
			//KgGlobalData::ms_pStack->aEmerStop = 1;
			//writeKgLogfile(QString("step3 EmerStopState pStack->usEmerStopState=%1").arg(KgGlobalData::ms_pStack->usEmerStopState));
		}
		else       // 正常
		{
			//KgGlobalData::ms_pStack->usEmerStopState = 2;
			//KgGlobalData::ms_pStack->aEmerStop = 0;
			//writeKgLogfile(QString("step4 EmerStopState pStack->usEmerStopState=%1").arg(KgGlobalData::ms_pStack->usEmerStopState));
		}
		// KgGlobalData::ms_pStack->aEmerStop = m_emergStopAlarm;
        // KgGlobalData::ms_pStack->aEnvTemp[11] = m_emergStopAlarmSec;
	}
}

void DryCtrlThread::judgeBmsLocalState()// added 2023-12-25
{
   if (KgGlobalData::ms_bmsLocalStrategy.diList.size() > 0) 
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_bmsLocalStrategy, KgGlobalData::ms_dryData.DIVal,3,strPos))
	   {
		   if(++m_bmsLocalCount >= KgGlobalData::ms_bmsLocalStrategy.confirmedCount) 
		   {
		   	   if (0 == m_bmsLocalState)
			   {	
			       if(isChLang())
			   	      saveLogToBaDb(kgConvert("BMS就地") + QString("(DI%1).").arg(strPos));
				   else
				   	  saveLogToBaDb(QString("Bms is local state(DI%1).").arg(strPos));
			   }
		   	   m_bmsLocalState  = 1;
			   sendLog(0, "******************Bms is local state");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_bmsLocalSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到BMS就地信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read Bms local signal(DI%1).").arg(strPos));
			   	}
			    m_bmsLocalSignal = 1;
		   }
		   
		   if (m_bmsLocalCount > 10000)  //防止次数太大溢出
		   {
			   m_bmsLocalCount = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_bmsLocalState)
		   {
		   	   if(isChLang())
		   	      saveLogToBaDb(kgConvert("BMS就地结束."));
			   else
				  saveLogToBaDb(QString("Bms local state is over."));
		   }
		   m_bmsLocalCount = 0;
		   m_bmsLocalState = 0;
		   m_bmsLocalSignal = 0;
	   }
       //KgGlobalData::ms_pStack->aEnvTemp[19] = m_bmsLocalState;
	}
}

void DryCtrlThread::judgeBmsRemoteState()
{
   if (KgGlobalData::ms_bmsRemmoteStrategy.diList.size() > 0) 
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_bmsRemmoteStrategy, KgGlobalData::ms_dryData.DIVal,3,strPos))
	   {
		   if(++m_bmsRemoteCount >= KgGlobalData::ms_bmsRemmoteStrategy.confirmedCount) 
		   {
		   	   if (0 == m_bmsRemoteState)
			   {	
			       if(isChLang())
			   	      saveLogToBaDb(kgConvert("BMS远方") + QString("(DI%1).").arg(strPos));
				   else
				   	  saveLogToBaDb(QString("Bms is remote state(DI%1).").arg(strPos));
			   }
		   	   m_bmsRemoteState  = 1;
			   sendLog(0, "******************Bms is remote state");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_bmsRemoteSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到BMS远方信号.") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read Bms remote signal(DI%1).").arg(strPos));
			   	}
			    m_bmsRemoteSignal = 1;
		   }
		   
		   if (m_bmsRemoteCount > 10000)  //防止次数太大溢出
		   {
			   m_bmsRemoteCount = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_bmsRemoteState)
		   {
		   	   if(isChLang())
		   	      saveLogToBaDb(kgConvert("BMS远方结束."));
			   else
				  saveLogToBaDb(QString("Bms remote state is over."));
		   }
		   m_bmsRemoteCount = 0;
		   m_bmsRemoteState = 0;
		   m_bmsRemoteSignal = 0;
	   }
       //KgGlobalData::ms_pStack->aEnvTemp[20] = m_bmsRemoteState;
	}
}

// added 2022-3-27
void DryCtrlThread::judgeFuseAlarm()
{
   if (KgGlobalData::ms_fuseStrategy.diList.size() > 0)  // 有采集熔断器信号
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_fuseStrategy, KgGlobalData::ms_dryData.DIVal,4,strPos))
	   {
		   if(++m_fuseCount >= KgGlobalData::ms_fuseStrategy.confirmedCount) 
		   {
		   	   if (0 == m_fuseAlarm)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生熔断器告警") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("Confirm fuse alarm(DI%1).").arg(strPos));
			   }
		   	   m_fuseAlarm  = 1;
			   sendLog(0, "******************fuseAlarm");
		   }
		   else
		   {
			    if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_fuseSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到熔断器信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read fuse signal(DI%1).").arg(strPos));
			   	}
			    m_fuseSignal = 1;
		   }
			
		   if (m_fuseCount > 10000)  //防止次数太大溢出
		   {
			   m_fuseCount = 10000;
		   }
	   }
	   else
	   {
	       if (1 == m_fuseAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("熔断器告警结束."));
				else
				   saveLogToBaDb(QString("Fuse alarm is over."));
		   }
		   m_fuseCount = 0;
		   m_fuseAlarm = 0;
		   m_fuseSignal = 0;
		   //sendLog(0, "fuseAlarm is 0");
	   }
	}
}

// 读取消防释放信号 // added 2022-4-6
void DryCtrlThread::judgeXfMotionMsg()
{
   if (KgGlobalData::ms_xfMotionStrategy.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_xfMotionStrategy, KgGlobalData::ms_dryData.DIVal, 5, strPos))
	   {
		   if(++m_xfMotionCount >= KgGlobalData::ms_xfMotionStrategy.confirmedCount) 
		   {
		   	   if (0 == m_xfMotionAlarm)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生消防释放") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("Fire motion alarm (DI%1).").arg(strPos));
			   }
		   	   m_xfMotionAlarm = 1;
			   sendLog(0, "******************Fire motion Alarm");
		   }
			
		   if (m_xfMotionCount > 10000)  //防止次数太大溢出
		   {
			   m_xfMotionCount = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_xfMotionAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("消防释放结束."));
				else
				   saveLogToBaDb(QString("Fire motion alarm over."));
		   }
		   m_xfMotionCount = 0;
		   m_xfMotionAlarm = 0;
	   }

#ifdef ND_VER_PROGRAM 	// 南都版本 
		if (m_xfMotionAlarm) // 消防释放
		{
			KgGlobalData::ms_pStack->usStackTotAlarm = KgGlobalData::ms_pStack->usStackTotAlarm | (1 << 7);
		}
		else  // 正常
		{
			KgGlobalData::ms_pStack->usStackTotAlarm = KgGlobalData::ms_pStack->usStackTotAlarm & (~(1 << 7));
		}
		//printf("===============================usStackTotAlarm %d\n", KgGlobalData::ms_pStack->usStackTotAlarm);
#endif
	}
}

// 读取消防预警信号 // added 2022-6-8
void DryCtrlThread::judgeXfWarmMsg()
{
   if (KgGlobalData::ms_xfWarmStrategy.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_xfWarmStrategy, KgGlobalData::ms_dryData.DIVal, 6, strPos))
	   {
		   if(++m_xfWarmCount >= KgGlobalData::ms_xfWarmStrategy.confirmedCount) 
		   {
		   	   if (0 == m_xfWarmMsg)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("消防三级预警") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("Fire warm (DI%1).").arg(strPos));
			   }
		   	   m_xfWarmMsg = 1;
			   sendLog(0, "****************** Fire warm.");
		   }
			
		   if (m_xfWarmCount > 10000)  //防止次数太大溢出
		   {
			   m_xfWarmCount = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_xfWarmMsg)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("消防三级预警结束."));
				else
				   saveLogToBaDb(QString("Fire warm over."));
		   }
		   m_xfWarmCount = 0;
		   m_xfWarmMsg = 0;
	   }
	}
}


void DryCtrlThread::judgeUpsAlarm()
{
   if (KgGlobalData::ms_upsAlmStrategy.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_upsAlmStrategy, KgGlobalData::ms_dryData.DIVal, 7, strPos))
	   {
		   if(++m_upsAlarmCount >= KgGlobalData::ms_upsAlmStrategy.confirmedCount) 
		   {
		   	   if (0 == m_upsAlarm)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("UPS故障") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("UPS Fault (DI%1).").arg(strPos));
			   }
		   	   m_upsAlarm = 1;
			   sendLog(0, "******************UPS Fault");
		   }
			
		   if (m_upsAlarmCount > 10000)  //防止次数太大溢出
		   {
			   m_upsAlarmCount = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_xfWarmMsg)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("UPS故障结束."));
				else
				   saveLogToBaDb(QString("UPS Fault over."));
		   }
		   m_upsAlarmCount = 0;
		   m_upsAlarm = 0;
	   }
	}
}

void DryCtrlThread::judgeDoorAlarm()
{
   if (KgGlobalData::ms_doorAlmStrategy.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_doorAlmStrategy, KgGlobalData::ms_dryData.DIVal, 8, strPos))
	   {
		   if(++m_doorAlarmCount >= KgGlobalData::ms_doorAlmStrategy.confirmedCount) 
		   {
		   	   if (0 == m_doorAlarm)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("门禁告警") + QString("(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("Door Alarm (DI%1).").arg(strPos));
			   }
		   	   m_doorAlarm = 1;
			   sendLog(0, "******************Door Alarm");
		   }
			
		   if (m_doorAlarmCount > 10000)  //防止次数太大溢出
		   {
			   m_doorAlarmCount = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_doorAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("门禁告警结束."));
				else
				   saveLogToBaDb(QString("Door Alarm over."));
		   }
		   m_doorAlarmCount = 0;
		   m_doorAlarm = 0;
	   }
	}
}


void DryCtrlThread::judgeDoorAlarmSec()
{
   if (KgGlobalData::ms_doorAlmStrategySec.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_doorAlmStrategySec, KgGlobalData::ms_dryData.DIVal, 8, strPos))
	   {
		   if(++m_doorAlarmCountSec >= KgGlobalData::ms_doorAlmStrategySec.confirmedCount) 
		   {
		   	   if (0 == m_doorAlarmSec)
			   {	
			   		//if(isChLang())
			   		   //saveLogToBaDb(QString("中控舱/开关柜舱门禁告警(DI%1).").arg(strPos));
			   		   // saveLogToBaDb(QString("%1.").arg(KgGlobalData::ms_doorAlmStrategySec.diName));
					//else
					   //saveLogToBaDb(QString("Door Alarm2(DI%1).").arg(strPos));
					saveLogToBaDb(KgGlobalData::ms_doorAlmStrategySec.diName);
			   }
		   	   m_doorAlarmSec = 1;
			   sendLog(0, "******************Door Alarm2");
		   }
			
		   if (m_doorAlarmCountSec > 10000)  //防止次数太大溢出
		   {
			   m_doorAlarmCountSec = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_doorAlarmSec)
		   {	
		   		//if(isChLang())
		   		   //saveLogToBaDb(QString("中控舱/开关柜舱门禁告警结束."));
		   		   //saveLogToBaDb(QString("%1结束.").arg(KgGlobalData::ms_doorAlmStrategySec.diName));
				//else
				   //saveLogToBaDb(QString("Door Alarm2 over."));
				saveLogToBaDb(KgGlobalData::ms_doorAlmStrategySec.diOverName);
		   }
		   m_doorAlarmCountSec = 0;
		   m_doorAlarmSec = 0;
	   }
       writeKgLogfile(QString("||||||||||||||||aStackTemp[4]=====:%1").arg((int)KgGlobalData::ms_pStack->aStackTemp[4]));
	   KgGlobalData::ms_pStack->aStackTemp[4] = m_doorAlarmSec;       // 门禁状态2    
	}
}

void DryCtrlThread::judgeAcFault()
{
   if (KgGlobalData::ms_acFaultStrategy.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_acFaultStrategy, KgGlobalData::ms_dryData.DIVal, 7, strPos))
	   {
		   if(++m_acFaultCount >= KgGlobalData::ms_acFaultStrategy.confirmedCount) 
		   {
		   	   if (0 == m_acFault)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("空调故障(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("AC Fault(DI%1).").arg(strPos));
			   }
		   	   m_acFault = 1;
			   sendLog(0, "******************AC Fault");
		   }
			
		   if (m_acFaultCount > 10000)  //防止次数太大溢出
		   {
			   m_acFaultCount = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_acFault)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("空调故障结束."));
				else
				   saveLogToBaDb(QString("AC Fault over."));
		   }
		   m_acFaultCount = 0;
		   m_acFault = 0;
	   }
	}
}

void DryCtrlThread::judgeLqFault()
{
   if (KgGlobalData::ms_lqFaultStrategy.diList.size() > 0)  
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_lqFaultStrategy, KgGlobalData::ms_dryData.DIVal, 7, strPos))
	   {
		   if(++m_lqFaultCount >= KgGlobalData::ms_lqFaultStrategy.confirmedCount) 
		   {
		   	   if (0 == m_lqFault)
			   {	
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("液冷机组故障(DI%1).").arg(strPos));
					else
					   saveLogToBaDb(QString("LQ Fault(DI%1).").arg(strPos));
			   }
		   	   m_lqFault = 1;
			   sendLog(0, "******************LQ Fault");
		   }
			
		   if (m_lqFaultCount > 10000)  //防止次数太大溢出
		   {
			   m_lqFaultCount = 10000;
		   }
	   }
	   else
	   {
	   	   if (1 == m_lqFault)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("液冷机组故障结束."));
				else
				   saveLogToBaDb(QString("LQ Fault over."));
		   }
		   m_lqFaultCount = 0;
		   m_lqFault = 0;
	   }
	}
}

// 2023-11-11 8个函数合并成1个
void DryCtrlThread::judgetResState()
{
   for(int index = 0; index < RES_STRATEGY_COUNT; ++index)
   {
	   XFStrategy &resStg = KgGlobalData::ms_resStrategy[index];
	   if (resStg.diList.size() > 0)  
	   {
		   QString strPos;
		   QString diName = resStg.diName;
		   QString diOverName = resStg.diOverName;
		   if (HasAlarmVal(resStg, KgGlobalData::ms_dryData.DIVal, 8, strPos))
		   {
		   	   m_reservedCount[index] += 1;
			   if(m_reservedCount[index] >= KgGlobalData::ms_doorAlmStrategy.confirmedCount) 
			   {
			   	   if (0 == m_reservedAlarm[index])
				   {	
	                    //if(isChLang()) 
				   		   //saveLogToBaDb(QString("#1备用信号告警(DI%1).").arg(strPos));
				   		   //saveLogToBaDb(QString("#UPS故障(DI%1).").arg(strPos)); 
				   		   //saveLogToBaDb(QString("%1.").arg(diName)); 
						//else
					       //saveLogToBaDb(QString("Resvered alarm1(DI%1).").arg(strPos));
					    saveLogToBaDb(diName); 
				   }
			   	   m_reservedAlarm[index] = 1;
				   sendLog(0, "******************Reserved Alarm1");
			   }
				
			   if (m_reservedCount[index] > 10000)  //防止次数太大溢出
			   {
				   m_reservedCount[index] = 10000;
			   }
		   }
		   else
		   {
		   	   if (1 == m_reservedAlarm[index])
			   {	
			        //if(isChLang())
				   		//saveLogToBaDb(QString("#1备用信号告警结束(DI%1).").arg(strPos));
				   		//saveLogToBaDb(QString("UPS故障结束(DI%1).").arg(strPos));
				   		//saveLogToBaDb(QString("%1结束.").arg(diName));
				   		//saveLogToBaDb(KgGlobalData::ms_resStrategy1.diOverName);
				   //else
					    //saveLogToBaDb(QString("Resvered alarm1 over."));
				    saveLogToBaDb(diOverName); 
			   }
			   m_reservedCount[index] = 0;
			   m_reservedAlarm[index] = 0;
		   }
		  // KgGlobalData::ms_pStack->aEnvTemp[index] = m_reservedAlarm[index];  
		}
   	}
}

// added 2021-12-28
// 判断是否有可燃气体信号，如有BAMS立即停机
bool DryCtrlThread::hasCombusGasAlarm()
{
	return m_combusGasAlarm;
	
	bool bEnabledAlarm = false; // 不使能 云浮1期只需将可燃气体信号传给后台，BA不需要做逻辑
	
	if(bEnabledAlarm)
	{
		return m_combusGasAlarm;
	}
	else
	{
		return 0;
	}
}

//added 2021-12-7 
void DryCtrlThread::judgeCombusGasAlarm()
{
   if (KgGlobalData::ms_combusGasStrategy.diList.size() > 0) // 有采集可燃气体信号
   {
	   QString strPos;
	   if (HasAlarmVal(KgGlobalData::ms_combusGasStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   if (++m_combusGasCount >= KgGlobalData::ms_combusGasStrategy.confirmedCount)
		   {
			   if (0 == m_combusGasAlarm)
			   {	if(isChLang())
			   		   saveLogToBaDb(kgConvert("发生可燃气体告警") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Confirm combustible gas alarm(DI%1).").arg(strPos));
			   }
			   /*if (999 == KgGlobalData::ms_pStack->usFireBankAddr)
		   	       m_combusGasAlarm  = 1;
			   else
			   	   m_combusGasDetectAlarm = 1;
			   */
			   m_combusGasAlarm  = 1;
			   sendLog(0, "******************CombustibleGasAlarm");
		   }
 		   else
		   {
		   	   if(1 == KgGlobalData::ms_isSaveDetaiLog && 0 == m_combusGasSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			   	{
			   		m_signalLogCount += 1;
			   		if(isChLang())
			   		   saveLogToBaDb(kgConvert("读取到可燃气体信号") + QString("(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Read combustible gas signal(DI%1).").arg(strPos));
			   	}
			    m_combusGasSignal = 1;
		   }
		   if (m_combusGasCount > 10000)  //防止次数太大溢出
		   {
			   m_combusGasCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_combusGasAlarm)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("可燃气体告警结束."));
				else
				   saveLogToBaDb(QString("Combustible gas alarm is cleared."));
		   }
		   m_combusGasCount = 0;
		   m_combusGasAlarm = 0;
		   m_combusGasDetectAlarm = 0;
		   m_combusGasSignal = 0;
	   }
	}
}

quint16 DryCtrlThread::getIsolSwitchAggrState()
{
	// 有配置隔离开关策略, 才检查隔离开关是否都闭合
	if(KgGlobalData::ms_isolSwitchStrategy.diList.size() == 0)
	{
		return 0;
	}
	
	int closedCount = 0;
    int openedCount = 0;
	int totalCount = 0;
	for(int k = 0; k < KgGlobalData::ms_isolSwitchStrategy.diList.size(); ++k)
	{
		if(isBankInStack(k)) // 第k簇投入
		{
			totalCount += 1;
			DI_STU diStu = KgGlobalData::ms_isolSwitchStrategy.diList[k];
			int maskVal = (1 << diStu.diIndex);
			int tmpState = 0;
			if(maskVal == (maskVal & KgGlobalData::ms_dryData.DIVal)) // 第k簇的隔离开关闭合
			{
				closedCount += 1;
				tmpState = 1;
			}
			else
			{
				openedCount += 1;
			}

			if (1 == KgGlobalData::ms_saveHlkgLog)
		   	{
			   
		    }
		}
	}

	if(closedCount > 0 && closedCount == totalCount) // 隔离开关都闭合
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

quint16 DryCtrlThread::getConfSwitchState()
{
	int iClosedCount = 0;
	int iOpenedCount = 0;
	int totalCount = 0;

	// 有采集汇流开关反馈, 才检查汇流开关是否都闭合
	if(KgGlobalData::ms_hlkgStrategy.diCfgList.size() == 0)
	{
		return 0;
	}
	
	for(int k = 0; k < KgGlobalData::ms_hlkgStrategy.diCfgList.size(); ++k)
	{
	    DI_STU diStu = KgGlobalData::ms_hlkgStrategy.diCfgList[k];
	    int tmpState = getConfSwitchState(KgGlobalData::ms_pStack, diStu);
		
		totalCount += 1;
	   
	    if(1 == tmpState)
	    {
			iClosedCount += 1;
	    }
	    else
	    {
			iOpenedCount += 1;
	    }
	}
	
	if(iClosedCount > 0 && iClosedCount == totalCount)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

void DryCtrlThread::judgetConfSwitchState(CBattStack *pStack)
{
	int iClosedCount = 0;
	int iOpenedCount = 0;
	int totalCount = 0;

	// 有采集汇流开关反馈, 才检查汇流开关是否都闭合
	// deleted 2022-3-26
	//if(KgGlobalData::ms_hlkgStrategy.diCfgList.size() == 0)
	//{
	//	return;
	//}
	
	//if (KgGlobalData::ms_hlkgStrategy.diCfg.diIndex < KgGlobalData::ms_devDiCount) // 有采集汇流开关反馈
	for(int k = 0; k < KgGlobalData::ms_hlkgStrategy.diCfgList.size(); ++k)
	{
	    DI_STU diStu = KgGlobalData::ms_hlkgStrategy.diCfgList[k];
	    int tmpState = getConfSwitchState(pStack, diStu);
		
		totalCount += 1;
	   
	    //if (hlkgMask == (hlkgMask & g_DIState))   //DI1值为1，汇流开关闭合
	    if(1 == tmpState)
	    {
	   		sendLog(0, QString("***Hlkg%1 Has HZ.").arg(k+1));
			iClosedCount += 1;
			// modified 2022-7-11
			/*
			if(0 == k) // added 2022-05-25
				pStack->usDI1 = 1; 
			else if(1 == k)
				pStack->usDI2 = 1;
			else if(2 == k)
				pStack->usDI3 = 1;
			else;
			*/
			//pStack->usDI2 = 1;
	    }
	    else
	    {
	   		sendLog(0, QString("***Hlkg%1 Has FZ.").arg(k+1));
			iOpenedCount += 1;
			/*
			if(0 == k) // added 2022-05-25
				pStack->usDI1 = 0;
			else if(1 == k)
				pStack->usDI2 = 0;
			else if(2 == k)
				pStack->usDI3 = 0;
			else;
			*/
			//pStack->usDI2 = 0;
	    }
		
		// 与BA主程序日志重复,汇流开关策略不是200时才输出 // modified 2022-11-18
	    if (1 == KgGlobalData::ms_saveHlkgLog && 200 != pStack->usConfSwitchStrategy)
	   	{
		   if ((0 == m_hlkgState[k]) && 1 == tmpState)     // || 99 == m_hlkgState
		   	{
		   		if(isChLang())
				{
		   			//saveLogToBaDb(QString("读取到串口继电器输入状态:%1.").arg(g_DIState));
		   			if(1 == KgGlobalData::ms_hlkgStrategy.diCfgList.size())
		   			   saveLogToBaDb(kgConvert("汇流开关合闸."));
					else
					   saveLogToBaDb(QString("#%1").arg(k+1) + kgConvert("汇流开关合闸."));
				}
				else
				{
		   			//saveLogToBaDb(QString("Read IO state:%1.").arg(g_DIState));
		   			if(1 == KgGlobalData::ms_hlkgStrategy.diCfgList.size())
		   			   saveLogToBaDb(QString("ConfSwitch is closed."));
					else
					   saveLogToBaDb(QString("#%1 ConfSwitch is closed.").arg(k+1));
						
				}
		   	}
		   else if((1 == m_hlkgState[k]) && 0 == tmpState) // || 99 == m_hlkgState
		   	{
		   		if(isChLang())
				{
		   			//saveLogToBaDb(QString("读取到串口继电器输入状态:%1.").arg(g_DIState));
		   			if(1 == KgGlobalData::ms_hlkgStrategy.diCfgList.size())
		   			  saveLogToBaDb(kgConvert("汇流开关分闸."));
					else
					  saveLogToBaDb(QString("#%1").arg(k+1) + kgConvert("汇流开关分闸."));
				}
				else
				{
		   			//saveLogToBaDb(QString("Read IO state:%1.").arg(g_DIState));
		   			if(1 == KgGlobalData::ms_hlkgStrategy.diCfgList.size())
		   			   saveLogToBaDb(QString("ConfSwitch is opened."));
					else
					   saveLogToBaDb(QString("#%1 ConfSwitch is opened.").arg(k+1));
				}
		   	}
		   else
		   	;
	   }

	   m_hlkgState[k] = tmpState;
	}

	if(iClosedCount > 0 && iClosedCount == totalCount)
	{
#ifdef MASTER_VER_CONF
	    //if (200 == pStack->usConfSwitchStrategy)// 汇流开关策略 200 - 3rd进程设定 汇流开关断开,才能闭合接触器
	   	{
		    pStack->usConfSwitchState = 1;//通知BA 汇流开关已经闭合
		}
		//pStack->usDI2 = 1;// deleted 2022-11-16
#else
		keepContCtrlOpened(pStack->usStackState,1);
#endif
		//pStack->usStackTemp[2] = 1; // 堆级断路器状态反馈信号 0--断开 1--闭合
	}
	else
	{
#ifdef MASTER_VER_CONF
	    //if (200 == pStack->usConfSwitchStrategy)
	   	{
		     pStack->usConfSwitchState = 2;//通知BA 汇流开关已经断开
		}
		//pStack->usDI2 = 0; // deleted 2022-11-16
		//pStack->usStackTemp[2] = 0; // 堆级断路器状态反馈信号 0--断开 1--闭合
#else
		keepContCtrlOpened(pStack->usStackState,0);
#endif	
	}
}

int g_isolSwitchClosedSignal = 0;
int g_isolSwitchOpenedSignal = 0;
int g_oldIsolSwitchAggrState = 99;
void DryCtrlThread::judgeIsolSwitchAggrState()
{
#ifdef LSZH_PRJ  //added 2021-5-13
    if ((0x0F & KgGlobalData::ms_dryData.DIVal) == 0x0) // 4个断路器都没有脱扣
	{
		m_emergStopAlarm = 0;
	}
	else // 有断路器脱扣
	{
		if (m_emergStopCount < 1000)
		{
			m_emergStopCount += 1;
		}
		
		if(m_emergStopCount >= 16) // 断路器断开维持20秒
		{
			if(0 == m_emergStopAlarm)
			{
				saveLogToBaDb(kgConvert("检测到断路器脱扣") + QString("(%1)").arg(KgGlobalData::ms_dryData.DIVal)
					+ kgConvert("，控制系统急停!"));
				m_emergStopAlarm = 1; // 通过急停告之BA跳机
			}
		}
	}
#endif

	// 有配置隔离开关策略, 才检查隔离开关是否都闭合
	if(KgGlobalData::ms_isolSwitchStrategy.diList.size() == 0)
	{
		return;
	}
	
	int closedCount = 0;
    int openedCount = 0;
	int totalCount = 0;
	for(int k = 0; k < KgGlobalData::ms_isolSwitchStrategy.diList.size(); ++k)
	{
		if(isBankInStack(k)) // 第k簇投入
		{
			totalCount += 1;
			DI_STU diStu = KgGlobalData::ms_isolSwitchStrategy.diList[k];
			int maskVal = (1 << diStu.diIndex);
			int tmpState = 0;
			if(maskVal == (maskVal & KgGlobalData::ms_dryData.DIVal)) // 第k簇的隔离开关闭合
			{
				closedCount += 1;
				tmpState = 1;
			}
			else
			{
				openedCount += 1;
			}

			if (1 == KgGlobalData::ms_saveHlkgLog)
		   	{
			   if ((0 == m_glkgState[k]) && 1 == tmpState)     // || 99 == m_hlkgState
			   	{
			   		if(isChLang())
					{
			   			if(1 == KgGlobalData::ms_isolSwitchStrategy.diList.size())
			   			   saveLogToBaDb(kgConvert("隔离开关闭合."));
						else
						   saveLogToBaDb(QString("#%1").arg(k+1) + kgConvert("隔离开关闭合."));
					}
					else
					{
			   			if(1 == KgGlobalData::ms_isolSwitchStrategy.diList.size())
			   			   saveLogToBaDb(QString("IsolSwitch is closed."));
						else
						   saveLogToBaDb(QString("#%1 IsolSwitch is closed.").arg(k+1));
							
					}
			   	}
			   else if((1 == m_glkgState[k]) && 0 == tmpState) 
			   	{
			   		if(isChLang())
					{
			   			if(1 == KgGlobalData::ms_isolSwitchStrategy.diList.size())
			   			  saveLogToBaDb(kgConvert("隔离开关断开."));
						else
						  saveLogToBaDb(QString("#%1").arg(k+1) + kgConvert("隔离开关断开."));
					}
					else
					{
			   			if(1 == KgGlobalData::ms_isolSwitchStrategy.diList.size())
			   			   saveLogToBaDb(QString("IsolSwitch is opened."));
						else
						   saveLogToBaDb(QString("#%1 IsolSwitch is opened.").arg(k+1));
					}
			   	}
			   else
			   	;
		   }
		   
		   m_glkgState[k] = tmpState;
		}
	}

	if(closedCount > 0 && closedCount == totalCount) // 隔离开关都闭合
	//if(closedCount > 0) // 至少有一个隔离开关闭合
	{
		m_isolSwitchOpendCount = 0;
		g_isolSwitchOpenedSignal = 0;
		if(m_isolSwitchClosedCount < 1000)
		{
			m_isolSwitchClosedCount += 1;
		}
		if(m_isolSwitchClosedCount >= KgGlobalData::ms_isolSwitchStrategy.confirmedCount)
		{
			SetIsolSwitchAggrState(1);
			if(1 != g_oldIsolSwitchAggrState)// added 2021-07-17 
			{
				g_oldIsolSwitchAggrState = 1;
				if(isChLang())
	   		      saveLogToBaDb(kgConvert("隔离开关闭合:") + QString("%1.").arg(KgGlobalData::ms_dryData.DIVal));
			    else
			      saveLogToBaDb(QString("All IsolSwitch is closed:%1.").arg(KgGlobalData::ms_dryData.DIVal));
			}
		}
		else
		{
			/*
			if(0 == g_isolSwitchClosedSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			{
				g_isolSwitchClosedSignal = 1;
				if(isChLang())
	   		      saveLogToBaDb(QString("收到隔离开关闭合信号:%1.").arg(KgGlobalData::ms_dryData.DIVal));
			    else
			      saveLogToBaDb(QString("Detect IsolSwitch closed signal:%1.").arg(KgGlobalData::ms_dryData.DIVal));
			}
			*/
		}
	}
	else
	{
        m_isolSwitchClosedCount = 0;
	    g_isolSwitchClosedSignal = 0;
		if(m_isolSwitchOpendCount < 1000)
		{
			m_isolSwitchOpendCount += 1;
		}
		if(m_isolSwitchOpendCount >= KgGlobalData::ms_isolSwitchStrategy.confirmedCount)
		{
			SetIsolSwitchAggrState(0); 
			if(0 != g_oldIsolSwitchAggrState)// added 2021-07-17 
			{
				g_oldIsolSwitchAggrState = 0;
				if(isChLang())
	   		      saveLogToBaDb(kgConvert("隔离开关断开:") + QString("%1.").arg(KgGlobalData::ms_dryData.DIVal));
			    else
			      saveLogToBaDb(QString("IsolSwitch is opened:%1.").arg(KgGlobalData::ms_dryData.DIVal));
			}
		}
		else
		{
		   /*
			if(0 == g_isolSwitchOpenedSignal && m_signalLogCount < SIGNAL_LOG_COUNT)
			{
				g_isolSwitchOpenedSignal = 1;
				if(isChLang())
	   		      saveLogToBaDb(QString("收到隔离开关断开信号:%1.").arg(KgGlobalData::ms_dryData.DIVal));
			    else
			      saveLogToBaDb(QString("Detect IsolSwitch opened signal:%1.").arg(KgGlobalData::ms_dryData.DIVal));
			}
		   */
		}
	}
/*	
#ifdef GSHT_PRJ //added 2021-5-27
     int closedCount = 0;
     int openedCount = 0;
	 for(int k = 0; k < 2; ++k) // 检查断路器1和2是否闭合
	 {
		if(isBankInStack(0))
		{
	        // 一直只判断第一簇，不对 现场测试只要第一簇合上，BA就会正常,这不对 2021-7-17
			if(1 == (1&g_DIState)) // 断路器闭合 
			{
				closedCount += 1;
			}
			else
			{
				openedCount += 1;
			}
		}
	}

	if(closedCount > 0 && openedCount == 0) // 都闭合
	{
		SetIsolSwitchAggrState(1);
	}
	else
	{
		SetIsolSwitchAggrState(0);
	}
#endif
*/
}

void DryCtrlThread::judgeMainSwitchState()
{
   if (KgGlobalData::ms_mainSwitchStrategy.diList.size() > 0) 
   {
	   QString strPos;

	   if (HasAlarmVal(KgGlobalData::ms_mainSwitchStrategy, KgGlobalData::ms_dryData.DIVal,1,strPos))
	   {
		   if (++m_mainSwitchCount >= KgGlobalData::ms_mainSwitchStrategy.confirmedCount)
		   {
			   if (0 == m_mainSwitchClosed)
			   {	if(isChLang())

			   		   saveLogToBaDb(kgConvert("主断路器闭合(DI%1).").arg(strPos));
			        else
					   saveLogToBaDb(QString("Main swich is closed(DI%1).").arg(strPos));
			   }
			   m_mainSwitchClosed  = 1;
			   sendLog(0, "******************Main swich is closed");
		   }
		   
		   if (m_mainSwitchCount > 10000)  //防止次数太大溢出
		   {
			   m_mainSwitchCount = 10000;
		   }
	   }
	   else
	   {
		   if (1 == m_mainSwitchClosed)
		   {	
		   		if(isChLang())
		   		   saveLogToBaDb(kgConvert("主断路器断开."));
				else
				   saveLogToBaDb(QString("Main swich is opened."));
		   }

		   m_mainSwitchCount = 0;
		   m_mainSwitchClosed = 0;
	   }

	   //KgGlobalData::ms_pStack->aEnvFireFault = m_fireFaultAlarm;
	   //KgGlobalData::ms_pStack->aFireFault = m_fireFaultAlarm;                        // 消防故障
	}
}
void DryCtrlThread::judgeChgJcqState()
{
    if (KgGlobalData::ms_diIndexChgDrive < KgGlobalData::ms_devDiCount) // 有充电接触器反馈
	{
		 int hlkgMask = 1 << KgGlobalData::ms_diIndexChgDrive;
		 int newChgJcqState = 0;
   		 if (hlkgMask == (hlkgMask & KgGlobalData::ms_dryData.DIVal))//DI1值为1，汇流开关闭合
   		 {
   			newChgJcqState = 1;// 充电接触器已经闭合
   		 }

	  	 if(1 == newChgJcqState  && 0 == m_usOldChgJcqState)
		 {
			if(isChLang())
			    saveLogToBaDb(kgConvert("充电接触器闭合."));
			else
				saveLogToBaDb(QString("Charge contactor is closed."));
		 }
		 
		 if(0 == newChgJcqState  && 1 == m_usOldChgJcqState)
		 {
			if(isChLang())
			    saveLogToBaDb(kgConvert("充电接触器断开."));
			else
				saveLogToBaDb(QString("Charge contactor is opened."));
		 }
		 m_usOldChgJcqState = newChgJcqState;
	}

	if (KgGlobalData::ms_diIndexDchgDrive < KgGlobalData::ms_devDiCount) // 有放电接触器反馈
	{
		 int hlkgMask = 1 << KgGlobalData::ms_diIndexDchgDrive;
		 int newDchgJcqState = 0;
   		 if (hlkgMask == (hlkgMask & KgGlobalData::ms_dryData.DIVal))
   		 {
   			newDchgJcqState = 1;// 放电接触器已经闭合
   		 }

	  	 if(1 == newDchgJcqState  && 0 == m_usOldDchgJcqState)
		 {
			if(isChLang())
			    saveLogToBaDb(kgConvert("放电接触器闭合."));
			else
				saveLogToBaDb(QString("Discharge contactor is closed."));
		 }
		 
		 if(0 == newDchgJcqState  && 1 == m_usOldDchgJcqState)
		 {
			if(isChLang())
			    saveLogToBaDb(kgConvert("放电接触器断开."));
			else
				saveLogToBaDb(QString("Discharge contactor is opened."));
		 }
		 m_usOldDchgJcqState = newDchgJcqState;
	}
}

int g_printErrCount = 0;
bool g_saveErrFlag = false;
//读取DI1--DI6的状态并判断消防告警
int DryCtrlThread::readDevDIState(CBattStack *pStack, quint16 &connFailedCount)
{
	bool  bHasEmerStopStrategy = false;
	bool  bHasWaterStrategy = false;
	//int   readByteCount = 0;
	
	if (0 == m_pIOReader->readDevDIState(0, KgGlobalData::ms_dryData))//查询成功
	{
		if (KgGlobalData::ms_dryData.readDiCount < 100)
		{
			KgGlobalData::ms_dryData.readDiCount += 1; 
		}

#ifdef ND_VER_PROGRAM   // 南都版本, 水浸由消防改变而来 2021-11-30  改xnview_zh.qm
        if (999 == pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4     紧急停机
		{
			bHasEmerStopStrategy = true;
		}
		bHasWaterStrategy = true; // added 2023-5-29
#else
		if (200 == pStack->usEmerStopStrategy)
		{
			bHasEmerStopStrategy = true;
		}
		
	    if (999 == pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4
	    {
      	    bHasWaterStrategy = true;
	    }
#endif

		//KgGlobalData::ms_dryData.bReadDiFlag = true;
	    //printf("get DI1-6 state:%d\n", g_DIState);
	    //处理读取到的DI信息 begin
	    //printf("pStack->usFireBankAddr======================%d\n", pStack->usFireBankAddr);
	    //if (999 == pStack->usFireBankAddr) // 999 - 接BA  消防接DI3 modified 2021-12-7
		{
	    	judgeXfAlarm();
			judgeXfSparyAlam();
			judgeXfFaultAlam();
            judgeXfAutoManu();
			judgeElecPowerOff();
			judgeCombusGasAlarm();
		}

		//if(bHasWaterStrategy)
		{
		    judgeWaterAlarm();
			judgeWaterAlarmSec();
		}
		
	    judgeThunderAlarm();
		judgeThunderAlarmSec();
		judgeFuseAlarm();
		judgeXfMotionMsg();
		judgeXfWarmMsg();
		judgeUpsAlarm();
		judgeDoorAlarm();
        judgeDoorAlarmSec();
		judgeAcFault();
		judgeLqFault();

		judgetResState();
		
		//if(bHasEmerStopStrategy)
		//{
	    	judgeEmergeStop();
		    judgeEmergeStopSec();
		//}
		
	    judgetConfSwitchState(KgGlobalData::ms_pStack);
		judgeIsolSwitchAggrState();
		judgeMainSwitchState();
		judgeChgJcqState();
		
		judgeBmsLocalState();
        judgeBmsRemoteState();
	   //处理读取到的DI信息 end
	}
	else
	{
		//if(1 == KgGlobalData::ms_pStack->aExIOModuConnFault) // added 2023-8-21
		if(1 == m_usConnFailed)
		{
			//for(int k = 0; k < 20; ++k)
			//    printf("readByteCount================%d\n", readByteCount);
			// 通信故障时，输出接收到的错误报文，最多输出3次 added 2023-8-21
			/*if(readByteCount > 0 && false == g_saveErrFlag && g_printErrCount < 1)
			{
				g_saveErrFlag = true;
				g_printErrCount += 1;
				
				QString strPrintInfo = "";
				QChar aFillChar = '0';

				for (int i = 0; i < readByteCount && i < 5; ++i)
				{
					strPrintInfo += QString("%1 ").arg((uchar)*(m_pIOReader->m_pDataBuf + i), 2, 16, aFillChar);
				}
				
				strPrintInfo = strPrintInfo.toUpper();
				strPrintInfo += ".";

				QString strLog;
				if(isChLang())
				   strLog = QString("接收IO信息[%1路]: ").arg(KgGlobalData::ms_dryData.devDiCount) + strPrintInfo;
				else
				   strLog = QString("Read IO data[%1DI]: ").arg(KgGlobalData::ms_dryData.devDiCount) + strPrintInfo;
				saveLogToBaDb(strLog);
			}*/
		}
	}
	return 0;
}

quint16 DryCtrlThread::getConfSwitchState(CBattStack *pStack, DI_STU diStu)
{
	quint16 state = 0; // 记录汇流开关是否闭合

	//if (KgGlobalData::ms_hlkgStrategy.diCfg.diIndex < m_devDoCount)
	//{
	   //int hlkgMask = 1 << KgGlobalData::ms_hlkgStrategy.diCfg.diIndex;
	   int hlkgMask = 1 << diStu.diIndex;
	   if(1 == diStu.alarmValue) // 检查到值为1（干结点闭合)表示汇流开关闭合  常用配置 modified 2021-06-22 
	   {
	   		if (hlkgMask == (hlkgMask & KgGlobalData::ms_dryData.DIVal))   //DI1值为1，汇流开关闭合
	   		{
	   			state = 1;//汇流开关已经闭合
	   		}
	   }
	   else // 检查到值为0（干结点断开)表示汇流开关闭合
	   {
	   		if (hlkgMask != (hlkgMask & KgGlobalData::ms_dryData.DIVal))   //DI1值为0，汇流开关闭合
	   		{
	   			state = 1;//汇流开关已经闭合
	   		}
	   }
	//}

	return state;
}

quint16 DryCtrlThread::getClosedConfSwitchCount()
{
   int closeCount = 0;
   
   for(int k = 0; k < KgGlobalData::ms_hlkgStrategy.diCfgList.size(); ++k)
	{
		DI_STU diStu = KgGlobalData::ms_hlkgStrategy.diCfgList[k];
		if (getConfSwitchState(KgGlobalData::ms_pStack,diStu) > 0)
		{
			 closeCount += 1;
		}
	}

   return closeCount;
}

QString DryCtrlThread::getConfSwitchStrState()
{
   QString strState;
   
   for(int k = 0; k < KgGlobalData::ms_hlkgStrategy.diCfgList.size(); ++k)
	{
		if(k > 0)
		{
			strState += QString("-");
		}
	    strState += QString("%1").arg(m_hlkgState[k]);
	}

   return strState;
}


//跳机时驱动分闸
quint16 DryCtrlThread::waitFzOpt(quint16 ctrlType, quint16 &drvFzCount, quint16 &drvFzSuccedCount, QDateTime &drvFzTime, QDateTime statChangeTime)
{
    QString strLog;
    quint16 usDrvFz = 0;
	
    if (0 == drvFzCount)// 还没有发送分闸命令 // 第一次一定会下发，不管是否已经分闸
   	{
   		if(!statChangeTime.isValid())
		{
			statChangeTime = QDateTime::currentDateTime();
		}
   	    /*
   	    if (getHlKgState(pStack) == 0)//DI1为0, 电操已分闸 2020-2-22 added
   	    {
   	         QDateTime nowTime = QDateTime::currentDateTime();
	   	     int elapseSec  = drvFzTime.secsTo(nowTime);
			 if (drvFzTime.isValid() && elapseSec < 120)//120秒内不重复执行
			 {
				 strLog = QString("drvFzCount:%1, waitFzOpt=====================================has FZ OK").arg(drvFzCount);
			     sendLog(0, strLog);
			     return 0;
			 }
   	    }
		*/
		
	    int cirCount = 0;
		while(1) // 延时处理：在断开接触器之前4秒，先控制汇流开关分闸
		{
		    if (++cirCount >= 3000)// 等待30秒还没有发送分闸命令，出错
		    {
				strLog = QString("Try drive FZ failed**********.");
			    sendLog(0, strLog);
		        break;
		    }
		    if ((cirCount%100) == 0)
		    {
				strLog = QString("WaitFzOpt ======== usDelayBeforeCutCntor:%1, wait time:%2S.")
					.arg(KgGlobalData::ms_pStack->usDelayBeforeCutCntor).arg(cirCount*10/1000.0);
			    sendLog(0, strLog);
		    }
			
			QDateTime nowTime = QDateTime::currentDateTime();
			qint64 elapseSec = statChangeTime.msecsTo(nowTime);
			
			//QString strInfo = statChangeTime.toString("hh:mm:ss   ") + nowDateTime.toString("hh:mm:ss");
			//sendLog(0, strInfo);
			
			int waitTime = 0;
			if (KgGlobalData::ms_pStack->usDelayBeforeCutCntor > 4)
			{
			   waitTime = KgGlobalData::ms_pStack->usDelayBeforeCutCntor-4;
			}
			
			if (elapseSec >= waitTime*1000)//故障发生超过Delay秒
			{
                drvFzCount += 1;
				usDrvFz = 1;//驱动分闸
				strLog = QString("WaitFzOpt ======== FZ, drvFzCount:%1.").arg(drvFzCount);
			    sendLog(0, strLog);
				
				if(1 == ctrlType)
				{
					//saveLogToBaDb(QString("控制汇流开关分闸."));
				}
				else
				{
					//saveLogToBaDb(QString("EMS控制汇流开关分闸."));
				}
				if(isChLang())
				    saveLogToBaDb(kgConvert("控制汇流开关分闸."));
				else
					saveLogToBaDb(QString("Control opening bus switch."));
				drvFzTime = nowTime;
				break;
			}
		    this->msleep(10);
		}
   	}
    else//已发送分闸命令
   	{
   	    //if (getHlKgState(KgGlobalData::ms_pStack) > 0)// DI1为1,电操还没断开
   	    if(getClosedConfSwitchCount() > 0) // 电操还没断开
   	    {
   	    	   if(1 == drvFzSuccedCount) // 前面已经分闸，现在刚又检测到合闸
			   	{
			   		if(1 == ctrlType)
					{
						//saveLogToBaDb(QString("控制汇流开关分闸."));
					}
					else
					{
						//saveLogToBaDb(QString("EMS控制汇流开关分闸."));
					}
					if(isChLang())
				    	saveLogToBaDb(kgConvert("控制汇流开关分闸."));
					else
						saveLogToBaDb(QString("Control bus switch opening."));
			   	}
   	    	    drvFzSuccedCount = 0;
   	        //if (drvFzCount < 3)//最多只试3次 modified 2021-9-19
   	        //{
	   	         QDateTime nowTime = QDateTime::currentDateTime();
	   	         int elapseSec  = drvFzTime.secsTo(nowTime);
				 strLog = QString("waitFzOpt================elapseSec:%1").arg(elapseSec);
			     sendLog(0, strLog);
				 
				 if (elapseSec >= 2)//至少过2秒还没有响应，重新发送命令 //10  modified 2021-9-19
				 {
					 if(++drvFzCount >= 30000)
					 {
					 	drvFzCount = 20000;
					 }
					 
					 if(drvFzCount < 150)  // 分闸不成功时，前5分钟每2秒操作一次 
					 {
					 	 usDrvFz = 1;//驱动分闸
					 }
					 else
					 {
					 	 if(150 == drvFzCount)
						 {
						 	if(isChLang())
						      saveLogToBaDb(kgConvert("控制汇流开关分闸失败."));
							else
						      saveLogToBaDb(QString("Control opening bus switch failed."));
						 }
					 	 if((drvFzCount%8) == 0)// 分闸不成功时，5分钟后每16秒操作一次
						 {
					 	 	usDrvFz = 1;//驱动分闸
					 	 }
					 }
				
					 strLog = QString("waitFzOpt================FZ, try drive FZ again, drvFzCount:%1, fzSuccedCount:%2.").arg(drvFzCount).arg(drvFzSuccedCount);
			         sendLog(0, strLog);
				     drvFzTime = nowTime;
				 }
   	        //}
			//else//分闸失败
			//{
			//	 strLog = QString("WaitFzOpt ********** FZ failed.");
			//   sendLog(0, strLog);
			//}
   	    }
		else//已经分闸
		{
		   strLog = QString("WaitFzOpt ======== has FZ OK, drvFzCount:%1, fzSuccedCount:%2.").arg(drvFzCount).arg(drvFzSuccedCount);
		   sendLog(0, strLog);
		   
			/*
		    uchar index = 0;
			bool  bHasEmerStopStrategy = false;
			bool  bHasWaterStrategy = false;
			
			m_pDataBuf[index++] = 0x99;
			m_pDataBuf[index++] = 06;  

			int regAddr = 0x5000;
			addParam2Buffer(m_pDataBuf+index, regAddr);// 起始地址:要查询的第一个光耦寄存器地址
			index += 2;

			int regVal = 0x1234;
			addParam2Buffer(m_pDataBuf+index, KgGlobalData::ms_devDiCount);// 寄存器个数:要查询的光耦寄存器数量
			index += 2;

			quint16 crcValue = Modbus_CRC16((uchar*)m_pDataBuf, index);
			addParam2Buffer(m_pDataBuf+index, crcValue);
			index += 2;

			int  nByte = m_pRtuClient->writeBlock((unsigned char*)m_pDataBuf, index);
			*/
		   
		   drvFzCount = 1;
		   
		   if(drvFzSuccedCount < 2) // 执行成功后再操作分闸2次
		   	{
		   		drvFzSuccedCount += 1;
				usDrvFz = 1;//驱动分闸
				drvFzTime = QDateTime::currentDateTime();
		   	}
		}
   	}

	return usDrvFz;
}

//驱动合闸
quint16 DryCtrlThread::waitHzOpt(quint16 ctrlType, quint16 &drvHzCount, QDateTime &drvHzTime)
{
    QString strLog;
    quint16 usDrvHz = 0;
	
    if (0 == drvHzCount)//还没有发送合闸命令
   	{
		//控制第1个DO口闭合
        drvHzCount += 1;
		usDrvHz = 1;//驱动合闸
		sendLog(0, QString("WaitHzOpt ======== HZ, drvHzCount:%1.").arg(drvHzCount));

		if(1 == ctrlType)
		{
			//saveLogToBaDb(QString("控制汇流开关合闸."));
		}
		else
		{
			//saveLogToBaDb(QString("EMS控制汇流开关合闸."));
		}
		if(isChLang())
		    saveLogToBaDb(kgConvert("控制汇流开关合闸."));
		else
		    saveLogToBaDb(QString("Control bus switch closing."));
		drvHzTime = QDateTime::currentDateTime();
   	}
    else//已发送合闸命令
   	{
   	    //if (getHlKgState(KgGlobalData::ms_pStack) > 0)//DI1为1,电操已经合上 2020-2-22 added
   	    if(getClosedConfSwitchCount() < KgGlobalData::ms_hlkgStrategy.diCfgList.size())
   	    {
   	         QDateTime nowTime = QDateTime::currentDateTime();
	   	     int elapseSec  = drvHzTime.secsTo(nowTime);
			 if (drvHzTime.isValid() && elapseSec < 120)//120秒内不重复执行
			 {
				 sendLog(0, QString("WaitHzOpt ======== has HZ OK, drvHzCount:%1.").arg(drvHzCount));
			     return 0;
			 }
   	    }
	 
   	    //if (getHlKgState(KgGlobalData::ms_pStack) == 0)//DI1为0, 电操还没合上
   	    if(getClosedConfSwitchCount() < KgGlobalData::ms_hlkgStrategy.diCfgList.size())
   	    {
   	        //if (drvHzCount < 3)//最多只试3次 modified 2021-9-19
   	        //{
	   	         QDateTime nowDateTime = QDateTime::currentDateTime();
	   	         int elapseSec  = drvHzTime.secsTo(nowDateTime);
				 strLog = QString("waitHzOpt================elapseSec:%1").arg(elapseSec);
				 sendLog(0, strLog);
				 
				 if (elapseSec >= 5)//至少过5秒还没有响应，重新发送命令// 10  modified 2021-9-19
				 {
				     drvHzCount += 1;
				     usDrvHz = 1;//驱动合闸 
					 strLog = QString("waitHzOpt================HZ, try drive HZ again, drvHzCount:%1").arg(drvHzCount);
				     sendLog(0, strLog);
				     drvHzTime = nowDateTime;
				 }
   	        //}
			//else //合闸失败
			//{
			//   //pStack->usStackTemp[27] = 0;
			//   KgGlobalData::ms_pStack->usStackTemp[12] = 0;
			//   strLog = QString("waitHzOpt ********** HZ failed");
			//   sendLog(0, strLog);
			//}
   	    }
		else //已经合闸, 修改合闸总次数，否则如果持续有合闸命令，但DI1突然变为0，则会继续发送合闸命令
		{
		   //pStack->usStackTemp[27] = 0;
		   KgGlobalData::ms_pStack->usStackTemp[12] = 0;
		}
   	}

	return usDrvHz;
}

void DryCtrlThread::parseStackState(quint16 stackState, quint16 &usHasProt, quint16 &usHasAlarm,
		quint16 &usChargeFull, quint16 &usDischargeEmpty, quint16 &usProhibitChgDchg)
{	
    usHasProt = 0; 
	usHasAlarm = 0;
	usChargeFull = 0;
	usDischargeEmpty = 0;
	usProhibitChgDchg = 0;
	
#ifdef MASTER_VER  // BA通用版本
	if (0xAAAA == stackState)
	{
	    usHasProt = 1;
	}
	else if (0x5555 == stackState)
	{
	    usHasAlarm = 1;
		usProhibitChgDchg = 1;
	}
	else if (0x1111 == stackState)
	{
	    usChargeFull = 1;
		usHasAlarm = 1;
	}
	else if (0x2222 == stackState)
	{
	    usDischargeEmpty = 1;
		usHasAlarm = 1;
	}
	else
		;
#endif

#ifdef ND_VER_PROGRAM 		// 南都版本
// 电池堆状态     0x1006    0 - 正常   1 - 禁充    2 - 禁放    3 - 待机     4 - 停机
	if (4 == stackState)
	{
	    usHasProt = 1;
	}
	else if (3 == stackState)
	{
	    usHasAlarm = 1;
		usProhibitChgDchg = 1;
	}
	else if (1 == stackState)
	{
	    usChargeFull = 1;
		usHasAlarm = 1;
	}
	else if (2 == stackState)
	{
	    usDischargeEmpty = 1;
		usHasAlarm = 1;
	}
	else
		;
#endif
}

// 如果有断路器断开，则强制为保护告警  //added 2021-5-13
void DryCtrlThread::lszhParseDLQState(quint16 &usHasProt)
{
	//if(1 == g_bReadDiFlag)//if(KgGlobalData::ms_dryData.bReadDiFlag)
	if(KgGlobalData::ms_dryData.readDiCount > 0)
	{
		if ((0x0F & KgGlobalData::ms_dryData.DIVal) == 0x0) // 4个断路器都没有脱扣
		{
		}
		else // 有断路器脱扣
		{
			usHasProt = 1;
		}
	}
}

int isSystemError(int stackState)
{
    int isError = 0;
	
#ifdef MASTER_VER  // BA通用版本
	if (0xAAAA == stackState)
	{
	    isError = 1;
	}
#endif

#ifdef ND_VER_PROGRAM 		// 南都版本
	if (4 == stackState)
	{
	    isError = 1;
	}
#endif
	return isError;
}

// added 2022-6-30
bool hasSomeProt()
{
	bool iHasProt = false;
   
    for(int k = 0; k < KgGlobalData::ms_installBankNum; ++k)
   	{
   	   CBattBank *pBank = KgGlobalData::ms_pRTDB->getBank(k);

	   if(pBank && isBankInStack(k))
	   {
	      // 放电温度上限保护   单体电压下限保护   组电压下限保护
	      if (pBank->aDchgTempUpLimitProt || pBank->aSglVolDownLimitProt || pBank->aBankVolDownLimitProt) 
		  	{
		  	    iHasProt = true;
				break;
		  	}
	   }
   	}

	return iHasProt;
}

// 判断是否有合闸命令 added 2022-1-25
int hasEmsHzCmd(CBattStack *pStack)
{
	bool retResult = false;
	
#ifdef MASTER_VER  // BA通用版本
	if(1 == pStack->usEMSConfCtrl)
	{
		retResult = true;
	}
#endif

	return retResult;
}

// 判断是否有分闸命令
int hasEmsFzCmd(CBattStack *pStack)
{
	bool retResult = false;
	
#ifdef MASTER_VER  // BA通用版本
	if(2 == pStack->usEMSConfCtrl)
	{
		retResult = true;
	}
#endif

	return retResult;
}

void clearEmsCmd(CBattStack *pStack)
{
#ifdef MASTER_VER  // BA通用版本
   //pStack->usEMSConfCtrl = 0;
#endif
}

quint16 DryCtrlThread::hasEmertStopAlarm()
{
	quint16 retResult = 0;
#ifdef MASTER_VER  // BA通用版本
	// 紧急停机状态             0 - 默认  1 - 告警  2 - 正常
	// modified 2022-05-27
	//if(1 == KgGlobalData::ms_pStack->usEmerStopState || m_emergStopAlarm > 0)
	if(m_emergStopAlarm > 0)
	{
		retResult = 1;
	}
#else
	if(m_emergStopAlarm > 0)
	{
		retResult = 1;
	}
#endif

	return retResult;// m_emergStopAlarm;
}

quint16  DryCtrlThread::hasFireAlarm()
{
	return m_fireAlarm;
}

int g_oldHlkgHzCount = 0;
bool DryCtrlThread::controlHzFz()
{
	quint16   usDrvFz = 0;    //是否驱动分闸
	quint16   usDrvHz = 0;    //是否驱动合闸
	QString strHint;
	int doIndex = 0;
	int k;

	CBattStack *pStack = KgGlobalData::ms_pStack;
	
    // step3. 判断是否需要分闸合闸操作
	//quint16   usDrvFz = 0;    //是否驱动分闸
	//quint16   usDrvHz = 0;    //是否驱动合闸
	int needBreakCnt = NeedBreakJCQCount();
    int needCloseCnt = NeedCloseJCQCount();
	int closedCnt = GetClosedJCQCount();
	int openedCnt = GetOpenedJCQCount();
	// 平高昆山usStackTemp[27], 许继江虹变usStackTemp[12] 27
	// quint16 emsCtrlHz = pStack->usStackTemp[27];//EMS控制的合闸分闸信号
	// pStack->usStackTemp[27] = 0;
	
	quint16 emsCtrlHz  = 0;
    quint16 tmpCmd  = 0;
	quint16 hasUsed = 0;
	
#ifdef ND_HNXJ	// added 2022-10-12
	hasUsed = true; // usStackTemp[27]已被使用
#endif

#ifdef HJ_5MWH	
	hasUsed = true; // usStackTemp[27]已被使用
#endif

	if(!hasUsed)
	{
		tmpCmd = pStack->usStackTemp[27];//EMS控制的合闸分闸信号, 1-上电, 2-下电
		if(tmpCmd > 0)
		{
		    pStack->usStackTemp[27] = 0;
			strHint = QString("@@@@@@@@@@@@@@@@@@@@pStack->usStackTemp[27]:%1.").arg(tmpCmd);
			sendLog(0, strHint);
		}
	}
	
// added 2023-2-18 // 接收界面的手动控制汇流开关命令(usStackTemp[29]:1-手动合闸  2-手动分闸)
	/*tmpCmd = 0;// pStack->usStackTemp[29];
    if(tmpCmd > 0)
    {
    	pStack->usStackTemp[29] = 0;
		if(1 == tmpCmd)   // 1-手动合闸
		{
			bool bSendCmd = sendHzFzCmd(1, 0);
			if(bSendCmd)
			{
				if(isChLang())
					saveLogToBaDb(QString("手动控制合闸."));
				else
					saveLogToBaDb(QString("Manual closing bus switch."));
				msleep(1000);
				return bSendCmd;
			}
		}
		else if(2 == tmpCmd) //  2-手动分闸
		{
			bool bSendCmd = sendHzFzCmd(0, 1);
			if(bSendCmd)
			{
				if(isChLang())
					saveLogToBaDb(QString("手动控制分闸."));
				else
					saveLogToBaDb(QString("Manual opening bus switch."));
				msleep(1000);
				return bSendCmd;
			}
		}
		else
			;
    }*/
// added end

#ifdef ND_VER_PROGRAM	
	if(1 == tmpCmd)     // 上电命令
	{  
	   // 并网连接状态  1 - 启动(Start Connection);  2 - 成功(Connection Successful);  3 - 结束(Process End)；
		if (2 == pStack->usConnState)  //  并网后才接收上电命令
		{
			emsCtrlHz = 1;
		}
		else
		{
			strHint = QString("***********************ND Ver, usConnState:%1, refuse to connect.").arg(pStack->usConnState);
			sendLog(0, strHint);
		}
	}
	else if(2 == tmpCmd)// 下电命令
	{
		emsCtrlHz = 2;
	}
	else
		;
	if(m_oldConnState != pStack->usConnState)
	{
		m_drvHzCount = 0;
	}
	m_oldConnState = pStack->usConnState;
	strHint = QString("***********************ND Ver data, usConnState:%1, emsCtrlHz:%2.").arg(pStack->usConnState).arg(emsCtrlHz);
	sendLog(0, strHint);
#else
   emsCtrlHz = tmpCmd;
	strHint = QString("=============emsCtrlHz:%1, usEMSContCtrl:%2, usEMSConfCtrl:%3.")
		.arg(emsCtrlHz).arg(pStack->usEMSContCtrl).arg(0);  // 堆接触器管理  // 汇流开关管理
	sendLog(0, strHint);
#endif
	strHint = QString("NeedBreakCnt:%1, needCloseCnt:%2, closedCnt:%3, openedCnt:%4, emsCtrlHz:%5.")
		.arg(needBreakCnt).arg(needCloseCnt).arg(closedCnt).arg(openedCnt).arg(emsCtrlHz);
	sendLog(0, strHint);

	// 1.BA故障时主动分闸  ************************************************
	if (KgGlobalData::ms_hlkgStrategy.fzDoList.size() > 0) // 有分闸干结点
	{	
	// 2022-01-09 (1)实现急停和消防时立刻断开汇流开关；(2)断开失败时不断重试分闸;(3)操作成功时再执行一次。
		if(hasEmertStopAlarm() || 1 == m_fireAlarm || 1 == m_waterAlarm) // 有 急停 或 消防告警
		{
			if(1 != m_usOldEmerStopState && hasEmertStopAlarm()) // 刚发生急停，需要立马断开汇流开关，不延时 added 2022-1-6
			{
				if(isChLang())
					saveLogToBaDb(kgConvert("急停,分闸汇流开关."));
				else
					saveLogToBaDb(QString("Emergency, closing bus switch."));
				m_drvFzCount = 1;
				m_drvFzSuccedCount = 0;
				usDrvFz = 1;
			}
			else if(0 == m_oldFireAlarm && 1 == m_fireAlarm)      // 刚发生消防，需要立马断开汇流开关，不延时 added 2022-1-6
			{
				if(isChLang())
					saveLogToBaDb(kgConvert("消防告警,分闸汇流开关."));
				else
					saveLogToBaDb(QString("Fire alarm, opening bus switch."));
				m_drvFzCount = 1;
				m_drvFzSuccedCount = 0;
				usDrvFz = 1;
			}
			else
			{
				/*
				if(0 == g_oldHlkgHzCount && getClosedConfSwitchCount() > 0) // 汇流开关还合上
				{
					m_drvFzCount = 1;
					usDrvFz = 1;
					saveLogToBaDb(QString("检测到汇流开关合闸,强制分闸."));
				}*/
				usDrvFz = waitFzOpt(1, m_drvFzCount, m_drvFzSuccedCount, m_drvFzTime, m_statChangeTime);
			}
		}
        else if (isSystemError(m_stackState) &&  needBreakCnt > 0)// BA故障，消防和急停时，驱动分闸
        {
            usDrvFz = waitFzOpt(1, m_drvFzCount, m_drvFzSuccedCount, m_drvFzTime, m_statChangeTime);
        }
#ifdef  YW0357_PRJ
		else if ((0x5555 == pStack->usStackState || 0x2222 == pStack->usStackState) && 
			hasSomeProt())// BA禁放，放电温度上限保护 或 单体电压下限保护时，驱动分闸   // added 2022-6-30
        {
            usDrvFz = waitFzOpt(1, m_drvFzCount, m_drvFzSuccedCount, m_drvFzTime, m_statChangeTime);
        }
#endif
		/*else if(1 == m_fireAlarm || 1 == m_emergStopAlarm) // 再判断一下会更好，保证消防和急停时会驱动分闸 added 2021-9-19
		{
			m_statChangeTime = QDateTime::currentDateTime();
			usDrvFz = waitFzOpt(m_drvFzCount, m_drvFzSuccedCount, m_drvFzTime, m_statChangeTime);
		}
		*/
		else
			;
		m_usOldEmerStopState = hasEmertStopAlarm();
		m_oldFireAlarm = m_fireAlarm;
	}
	
	g_oldHlkgHzCount = getClosedConfSwitchCount();

	// 2.检测异常情况，有必要时主动分闸  ************************************************
    // added 2020-5-21 检测接触器断开,但汇流开关合闸状态，如有过30秒主动分闸
	if (0 == usDrvFz && 0 == usDrvHz && KgGlobalData::ms_hlkgStrategy.fzDoList.size() > 0) // 当前没有驱动合闸分闸 
	{
		//if(openedCnt > 0 && (getHlKgState(pStack) > 0))// 有接触器断开，汇流开关还处于合闸状态
		if(openedCnt > 0 && (getClosedConfSwitchCount() > 0))
		{
		    m_detectYcCount += 3; // 先计时
		    sendLog(0, QString("Step501 detectYcCount:%1.").arg(m_detectYcCount));
		}
		else // 数据清0
		{
		    m_detectYcCount = 0;
			m_masterFzCount = 0;
			sendLog(0, QString("Step502 clear detectYcCount."));
		}

		if (m_detectYcCount >= 30*4) // 维持30秒后，主动进行分闸
		{
		   if (m_masterFzCount < 1) // 只下发1次
			{
				usDrvFz = 1;
				m_masterFzCount += 1;
				sendLog(0, QString("***Master FZ."));
				if(isChLang())
				 {
				    saveLogToBaDb(kgConvert("接触器已断开,强制分闸汇流开关."));
				 }
				 else
				 {
				 	saveLogToBaDb("Contactor has been opened, opening bus switch.");
				 }
			}
		}
	}
	
	// 3.配置为自动合闸时，接触器都闭合后主动合闸  ************************************************
	if (1== KgGlobalData::ms_hzEnabled && 0 == usDrvFz && 0 == usDrvHz &&
		 KgGlobalData::ms_hlkgStrategy.hzDoList.size() > 0) // 当前没有驱动合闸分闸 
	{
        int hasConfError = 0; // 是否已有汇流开关故障, 如有则拒绝合闸
#ifdef DETECT_CONF_ERROR
	    hasConfError = pStack->usStackTemp[28];
#endif
		if (0 == m_fireAlarm && 0 == hasEmertStopAlarm() && 0 == hasConfError)
		{
			// 所有电池组接触器都闭合, 汇流开关还处于分闸状态
		   // if(closedCnt >= KgGlobalData::ms_bankNumInStack && (getHlKgState(pStack) == 0)) 
		   if(0 == isSystemError(m_stackState) &&  closedCnt >= KgGlobalData::ms_bankNumInStack && (getClosedConfSwitchCount() < KgGlobalData::ms_hlkgStrategy.diCfgList.size())) 
		    {
		        m_detectOkCount += 3; // 先计时
			    sendLog(0, QString("Step503 detectOkCount:%1.").arg(m_detectOkCount));
		    }
			else // 数据清0
			{
			    m_detectOkCount = 0;
				m_masterHzCount = 0;
				sendLog(0, QString("Step504 clear detectOkCount."));
			}

			if (m_detectOkCount >= 15) // 维持15秒后，主动进行合闸
			{
			   m_detectOkCount = 0;
			   
			   if (m_masterHzCount < 3) // 只下发3次
				{
					usDrvHz = 1;
					m_masterHzCount += 1;
					sendLog(0, QString("***Master HZ."));
					if(1 == m_masterHzCount)
					{
						 if(isChLang())
						 {
						    saveLogToBaDb(kgConvert("接触器已闭合,强制合闸汇流开关."));
						 }
						 else
						 {
						 	saveLogToBaDb("Contactor has been closed, closing bus switch.");
						 }
					}
				}
			}

			/*if (detectOkCount >= 30) // 维持30秒后，再主动进行合闸
			{
			   if (masterHzCount < 2) // 只下发1次
				{
					usDrvHz = 1;
					masterHzCount += 1;
					sendLog(0, QString("try master HZ again"));
				}
			}*/
		}
	}
	//added end

	// 4.接受EMS的合闸分闸命令  ************************************************
	if (0 == usDrvFz && 0 == usDrvHz) // 当前没有驱动合闸分闸 
	{
	   if (1 == emsCtrlHz || hasEmsHzCmd(pStack)) //驱动合闸 // || 1 == pStack->usEMSConfCtrl
		{ 
			if(hasEmsHzCmd(pStack))//if(1 == pStack->usEMSConfCtrl) // added 2022-1-19
		   	{
		       clearEmsCmd(pStack);//  pStack->usEMSConfCtrl = 0; 
			}
			
		    for(int k = 0; k < 10; ++k)
			{
			   sendLog(0, QString("============================================1Recv HZ cmd from EMS.")); 
			}
			
		    if(!isSystemError(m_stackState) && closedCnt >= KgGlobalData::ms_bankNumInStack) // 无故障，且所有电池组接触器都闭合
		   	{
			    //sendLog(0, QString("=====Recv HZ cmd from EMS.")); 
			    for(int k = 0; k < 10; ++k)
				{
				  sendLog(0, QString("============================================2Recv HZ cmd from EMS.")); 
				}
			    usDrvHz = 1;//驱动合闸
			    //usDrvHz = waitHzOpt(2, m_drvHzCount, m_drvHzTime);

			    if (m_saveEmsCtrlHzRdCount < 5) 
			   	{
			   		m_saveEmsCtrlHzRdCount += 1;
					if(1 == emsCtrlHz)
					{
						if(isChLang())
						  saveLogToBaDb(kgConvert("远程控制合闸."));
						else
						  saveLogToBaDb(QString("Remote closing bus switch."));
					}
			   		else
					{
						if(isChLang())
						   saveLogToBaDb(kgConvert("远程控制合闸(BMS控制)."));
						else
						   saveLogToBaDb(QString("Remote closing bus switch(BMS control)."));
					}
			   	}
		    }
		    else  // 有电池组接触器没有闭合，拒绝合闸命令
		   	{
		   	    sendLog(0, QString("=====Reject HZ cmd from EMS."));
				if (m_saveRejectEmsHzRdCount < 5) 
			   	{
			   		m_saveRejectEmsHzRdCount += 1;
					if(1 == emsCtrlHz)
					{
						if(isChLang())
						   saveLogToBaDb(kgConvert("条件不具备，拒绝远程合闸."));
						else
						   saveLogToBaDb(QString("Reject remote closing bus switch."));
					}
			   		else
					{
						if(isChLang())
						   saveLogToBaDb(kgConvert("条件不具备，拒绝远程合闸(BMS控制)."));
						else
						   saveLogToBaDb(QString("Reject remote closing bus switch(BMS control)."));
					}
			   	}
		   	}
		}  
		else if (2 == emsCtrlHz || hasEmsFzCmd(pStack))//驱动分闸 // || 2 == pStack->usEMSConfCtrl
		{ 
		   //sendLog(0, QString("=====Recv FZ cmd from EMS."));
		   if(hasEmsFzCmd(pStack))//if(2 == pStack->usEMSConfCtrl) // added 2022-1-19
		   	{
		        clearEmsCmd(pStack);//   pStack->usEMSConfCtrl = 0;
			}
		   
		    for(int k = 0; k < 10; ++k)
			{
		        sendLog(0, QString("=================================================Recv FZ cmd from EMS."));
			}
		    usDrvFz = 1;//驱动分闸
		    //usDrvFz = waitFzOpt(2, m_drvFzCount, m_drvFzSuccedCount, m_drvFzTime, m_statChangeTime);
		   
		    if (m_saveEmsCtrlFzRdCount < 5) 
		   	{
		   		m_saveEmsCtrlFzRdCount += 1;
				if(2 == emsCtrlHz)
				{
					if(isChLang())
			   		   saveLogToBaDb(kgConvert("远程控制分闸."));
					else
					   saveLogToBaDb(QString("Remote opening bus switch."));
				}
				else
				{
					if(isChLang())
			   		   saveLogToBaDb(kgConvert("远程控制分闸(BMS控制).")); 
					else
					   saveLogToBaDb(QString("Remote opening bus switch(BMS control)."));
				}
		   	}
		}
		else
			;
	}
	
	// step4.下发控制DO1--DO6干结点命令
	bool bSendCmd = sendHzFzCmd(usDrvHz, usDrvFz);
#ifdef DETECT_CONF_ERROR
	detectConfSwitchError(usDrvHz, usDrvFz);
#endif

	return bSendCmd;
}

bool DryCtrlThread::sendHzFzCmd(quint16  usDrvHz, quint16  usDrvFz)
{
	bool bSendCmd = false;
	int k;
	int doIndex;
	
	 //发送合闸命令DO1
    //setDoStateHZ(KgGlobalData::ms_hlkgStrategy.hzDoIndex, usDrvHz);	
	if (KgGlobalData::ms_hlkgStrategy.hzDoList.size() > 0)
	 {
	    if (usDrvHz) // 需要合闸*************************
	    {
			/*
			g_DOState |= (1 << KgGlobalData::ms_hlkgStrategy.hzDoIndex);
			setDevAllDoState();
			
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000;
	        this->msleep(delayTime);//延时300ms
			g_DOState &= ~(1 << KgGlobalData::ms_hlkgStrategy.hzDoIndex);
			setDevAllDoState();
			*/
			
			openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.hzDoList);
			//for (k = 0; k < KgGlobalData::ms_hlkgStrategy.hzDoList.size(); ++k) // 先闭合
			//{
			//	doIndex = KgGlobalData::ms_hlkgStrategy.hzDoList[k];
			//	KgGlobalData::ms_dryData.IOCtrl |= (1 << doIndex);
			//}
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000;
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,delayTime);

			closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.hzDoList);
			//for (k = 0; k < KgGlobalData::ms_hlkgStrategy.hzDoList.size(); ++k) // 再断开
			//{
			//	doIndex = KgGlobalData::ms_hlkgStrategy.hzDoList[k];
			//	KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
			//}
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,0);
			m_pIOReader->DealwithSetDoCmd(0,KgGlobalData::ms_dryData); // 执行控制分闸命令
		
			bSendCmd = true;
	    }
	 }
			
    //发送分闸命令DO2
    //setDoStateFZ(KgGlobalData::ms_hlkgStrategy.fzDoIndex, usDrvFz);	
	if (KgGlobalData::ms_hlkgStrategy.fzDoList.size() > 0)
	 {
	    if (usDrvFz)// 需要分闸*************************
	    {
	        /*
			g_DOState |= (1 << KgGlobalData::ms_hlkgStrategy.fzDoIndex);
			setDevAllDoState();
			
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000;
	        this->msleep(delayTime);//延时300ms
			g_DOState &= ~(1 << KgGlobalData::ms_hlkgStrategy.fzDoIndex);
			setDevAllDoState();
			*/
			openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.fzDoList);// 先闭合

			/*if(1 == m_fireAlarm || 1 == m_waterAlarm || 1 == m_combusGasAlarm) // 发生了消防告警
			{
				if(m_xfTkMotionCount < 3)
				{
					m_xfTkMotionCount += 1;
				}
				openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.xfTkDoList);// 先闭合
				if(0 == m_xfTkMotionLogCount)
				{
					m_xfTkMotionLogCount = 1;
					doIndex = KgGlobalData::ms_hlkgStrategy.xfTkDoList.at(0);
					if(isChLang())
					   saveLogToBaDb(QString("消防告警分励脱扣(DO%1).").arg(doIndex+1));
					else
					   saveLogToBaDb(QString("Fire alarm, open switch(DO%1).").arg(doIndex+1));
				}
			}

	        bool isVolDownProt = hasVolDownPort();
			if(isVolDownProt) // 发生了低电压保护
			{
				if(m_volDownProtTkCount < 3)
				{
					m_volDownProtTkCount += 1;
				}
				openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList);// 先闭合
				if(KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList.size() > 0 && 0 == m_volDownProtTkLogCount)// modifed 2022-11-17
				{
					m_volDownProtTkLogCount = 1;
					doIndex = KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList.at(0);
					if(isChLang())
					   saveLogToBaDb(QString("低电压保护分励脱扣(DO%1).").arg(doIndex+1));
					else
					   saveLogToBaDb(QString("Vol down protect, open switch(DO%1).").arg(doIndex+1));
				}
			}*/
			
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000; /////////////////////////////////////////
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,delayTime);

			closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.fzDoList);// 再断开

			/*if(1 == m_fireAlarm || 1 == m_waterAlarm || 1 == m_combusGasAlarm) // 发生了消防告警
			{
				closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.xfTkDoList);// 再断开
			}

			if(isVolDownProt)   // 发生了低电压保护
			{
				closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList);// 再断开
			}*/
	
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,0);
			m_pIOReader->DealwithSetDoCmd(0,KgGlobalData::ms_dryData); // 执行控制合闸命令

			msleep(300); // 否则分闸干节点两次控制，中间会断开时间太短 // added 2022-11-17
			
			bSendCmd = true;
	    }
	 }

	return bSendCmd;
}

void DryCtrlThread::detectConfSwitchError(quint16 usDrvHz, quint16 usDrvFz)
{
	if(usDrvHz > 0)
	{
		m_sendHzCount += 1;
	}
	else if(usDrvFz > 0)
	{
		m_sendHzCount  = 0;
	}
	else
		;
	
	CBattStack *pStack = KgGlobalData::ms_pStack;
	if(m_sendHzCount >= 3) // 执行了3次合闸命令
    {
    	if(getClosedConfSwitchCount() < KgGlobalData::ms_hlkgStrategy.diCfgList.size())
    	{
    		if(1 != pStack->usStackTemp[28])
    		{   
    		    if(isChLang())
    			   saveLogToBaDb(kgConvert("汇流开关合闸失败."));
				else
				   saveLogToBaDb(QString("Control closing bus switch failed."));
    		}
    		pStack->usStackTemp[28] = 1; // 1-合闸失败  2-汇流开关异常断开
    	}
	}

	if(m_sendHzCount > 0)// 最后一次下发的是合闸命令
	{
		bool hzSucceed = 0;
		if(getClosedConfSwitchCount() == KgGlobalData::ms_hlkgStrategy.diCfgList.size())
    	{
    		hzSucceed  = 1;
    	}
		
		if(m_hzSucced > 0 && 0 == hzSucceed) // 起先检测到合闸，后来检测到分闸
		{
			if(2 != pStack->usStackTemp[28])
    		{
				if(isChLang())
    			   saveLogToBaDb(kgConvert("汇流开关异常断开."));
				else
				   saveLogToBaDb(QString("Bus switch is abnormally opened."));
    		}
			pStack->usStackTemp[28] = 2; // 1-合闸失败  2-汇流开关异常断开
		}
		m_hzSucced = hzSucceed;
	}
	
	if(1 == pStack->usStackTemp[29])     // 收到清除命令
	{
		pStack->usStackTemp[28] = 0;
		pStack->usStackTemp[29] = 0;
		m_sendHzCount = 0;
	}
}

void DryCtrlThread::dealwithConnFailed(int runCount)
{
    // added 2021-3-23
	int connAlarmCount = KgGlobalData::ms_connTimeoutCount;
	if (runCount <  30)     // 程序刚启动时，只需要1次通信故障，就通知BA急停
	{
		connAlarmCount = 1;
	}
	/*else if (30 == runCount)// 启动完毕
	{
		// 原来为通迅故障控制BA停机，则需要继续维持,直到通信正常
		if (g_connFailedCount >= 1 && g_connFailedCount < KgGlobalData::ms_connTimeoutCount)
		{
			g_connFailedCount = KgGlobalData::ms_connTimeoutCount;
			printf("****************************\n");
		}
	}*/
	else
		;
	//added end
	bool bHasEmerStopStrategy = false;
		
#ifdef	HAS_EMER_STOP_STRATEGY  // added 2021-3-13
	if (200 == KgGlobalData::ms_pStack->usEmerStopStrategy)
	{
		bHasEmerStopStrategy = true;
	}
#else
	if (999 == KgGlobalData::ms_pStack->usWaterBankAddr)// 电池组地址 0 - 未配置 999 - 接BA  水浸接DI4     紧急停机
	{
		bHasEmerStopStrategy = true;
	}
#endif	

	if (KgGlobalData::ms_dryData.failedCount >= connAlarmCount) // 通迅故障
	{
		 KgGlobalData::ms_pStack->aExIOModuConnFault = 1;  // added 2022-5-22
		 if (0 == m_usConnFailed || 99 == m_usConnFailed) // have not saved connect errer rd
		 {	
		     QString strErrData;
			 QChar c = '0';
			 for(int k = 0; k < KgGlobalData::ms_dryData.usErrorLen && k < 3; ++k)
			 {
				if(k > 0)
				{
					strErrData += " ";
				}
				strErrData += QString("%1").arg((int)KgGlobalData::ms_dryData.errorBuf[k], 2, 16, c);
			 }
			 
			 if(isChLang())
			 {
			   /*if (bHasEmerStopStrategy && KgGlobalData::ms_emgStopStrategy.diList.size() > 0) // 有采集急停信号
			   {
			       saveLogToBaDb(QString("串口继电器通信故障-急停."));
			   }
			   else
			   {
			   	   saveLogToBaDb(QString("串口继电器通信故障."));
			   }
			   */
			    QString strLog;
			    if(0 == KgGlobalData::ms_dryData.readDiCount)
			   	{	
			   		if(KgGlobalData::ms_dryData.usErrorLen > 0)// modified 2023-11-17
			   		{
			   		   // strLog = kgConvert("串口继电器通信故障(%1),版本:%2.").arg(strErrData).arg(getAppVer());
			   			strLog = kgConvert("串口继电器通信故障") + QString("(%1)").arg(strErrData) + 
							kgConvert(",版本:") + QString("%1.").arg(strErrData).arg(getAppVer());
			   		}
					else
					{
						//strLog = kgConvert("串口继电器通信故障,版本:%1.").arg(getAppVer());
						strLog = kgConvert("串口继电器通信故障")         +
							kgConvert(",版本:") + QString("%1.").arg(strErrData).arg(getAppVer());
						
					}
			   	}
			    else
			   	{
			   		//strLog = kgConvert("串口继电器通信故障,状态:%1,%2,版本:%3.").arg(KgGlobalData::ms_dryData.DIVal)
					//	.arg(KgGlobalData::ms_dryData.IOCtrl).arg(getAppVer());
					strLog = kgConvert("串口继电器通信故障,状态:") ;
					strLog += QString("%1,%2").arg(KgGlobalData::ms_dryData.DIVal).arg(KgGlobalData::ms_dryData.IOCtrl);
					strLog += kgConvert(",版本:") ;
					strLog += QString("%1.").arg(getAppVer());
				
			   	}
			    saveLogToBaDb(strLog);
			 }
			 else
			 {
			 	/*if (bHasEmerStopStrategy && KgGlobalData::ms_emgStopStrategy.diList.size() > 0) // 有采集急停信号
			 	{
			 	    saveLogToBaDb("Connect to IO module Failed, Emergency Stop.");
				}
				else
				{
				    saveLogToBaDb("Connect to IO module Failed.");
				}
				*/
				QString strLog;
			    if(0 == KgGlobalData::ms_dryData.readDiCount)
			   	{
			   		if(KgGlobalData::ms_dryData.usErrorLen > 0)
			   		{
			   			strLog = QString("Connect to IO module failed(%1),Ver:%2.").arg(strErrData).arg(getAppVer());
			   		}
					else
					{
						strLog = QString("Connect to IO module failed,Ver:%1.").arg(getAppVer());
					}
			   	}
			    else
			   	{
			   		strLog = QString("Connect to IO module failed,status:%1,%2,Ver:%3.").arg(KgGlobalData::ms_dryData.DIVal).arg(KgGlobalData::ms_dryData.IOCtrl)
						    .arg(getAppVer());
			   	}
			    saveLogToBaDb(strLog);
			 }
		 }
		 m_usConnFailed = 1;
	}
	else if (0 == KgGlobalData::ms_dryData.failedCount)// 通迅正常
	{
		 KgGlobalData::ms_pStack->aExIOModuConnFault = 0;
		 if (1 == m_usConnFailed) // have not saved connect OK rd // || 99 == m_usConnFailed
		 {
			if(isChLang())
			 {
			 	 QString strLog = kgConvert("串口继电器通信恢复.");
			     saveLogToBaDb(strLog);
			 }
			 else
			 {
				 QString strLog = QString("Reconnect to IO module OK.");
			     saveLogToBaDb(strLog);
			 }
		 }
		 m_usConnFailed = 0;
	}
	else
		;
	
	//if (usConnFailed || hasEmertStopAlarm()) // 通迅故障也作为急停处理 道威7.5MWh
	//if (hasEmertStopAlarm())
	//if (m_usConnFailed || hasEmertStopAlarm() || m_fuseAlarm > 0) 
	//if (hasEmertStopAlarm() || m_fuseAlarm > 0) // modified 2023-2-10
	if (hasEmertStopAlarm()) 
	{
		SetEmergeStopAlarm(1);
	}
	else
	{
		SetEmergeStopAlarm(0);
	}

	sendLog(0, QString("runCount:%1, readDiCount:%2, failedCount:%3, connAlarmCount:%4, m_usConnFailed:%5")
	.arg(runCount).arg(KgGlobalData::ms_dryData.readDiCount).arg(KgGlobalData::ms_dryData.failedCount).arg(connAlarmCount).arg(m_usConnFailed));
	if (m_usConnFailed)
	{
		sendLog(0, "******Connect IO dev Failed");
	}
}


quint16 oldFireAlarm = 0;
quint16 oldThunderAlarm = 0;
quint16 oldEmergStopAlarm = 0;
void DryCtrlThread::setSomeDOState()
{
	int k;
	int doIndex;
	QString strHint;

	quint16 usHasProt = 0; 
	quint16 usHasAlarm = 0;
	quint16 usChargeFull = 0;
	quint16 usDischargeEmpty = 0;
	quint16 usProhibitChgDchg = 0;
	quint16 usXfTkMotion = 0;
	quint16 usEmergStopAlarm = 0;
	
	// step2.获取BAMS的运行状态
	sendLog(0, QString("Waiting stack state changed..."));
	for(int k = 0; k < 25; ++k)//wait 0.5 seconds
	{
	    this->msleep(20);
	    if (m_stackState != KgGlobalData::ms_pStack->usStackState)
	   	{
	   	    m_stackState = KgGlobalData::ms_pStack->usStackState;	
		   	m_statChangeTime = QDateTime::currentDateTime();
			m_drvFzCount = 0;
			m_drvHzCount = 0;
			m_drvFzSuccedCount = 0;
			m_drvHzSuccedCount = 0;

			m_saveEmsCtrlHzRdCount = 0;
			m_saveEmsCtrlFzRdCount = 0;
			m_saveRejectEmsHzRdCount = 0;
			sendLog(0, QString("StackState has Changed."));
			break;
	   	}
		
		if (oldFireAlarm != m_fireAlarm) // 需要及时响应，不再延时
		{
			sendLog(0, QString("FireAlarm state has Changed."));
			break;
		}
		
		if (oldThunderAlarm != m_thunderAlarm) // 需要及时响应，不再延时
		{
			sendLog(0, QString("ThunderAlarm state has Changed."));
			break;
		}

		if(hasEmertStopAlarm()) // 紧急停机状态             0 - 默认  1 - 告警  2 - 正常
		{
			usEmergStopAlarm = 1;
		}
		else
		{
			usEmergStopAlarm = 0;
		}

		if (oldEmergStopAlarm != usEmergStopAlarm) // 需要及时响应，不再延时
		{
			sendLog(0, QString("EmergStopAlarm state has Changed."));
			break;
		}
	}
	
	parseStackState(m_stackState, usHasProt, usHasAlarm, usChargeFull, usDischargeEmpty, usProhibitChgDchg);
#ifdef LSZH_PRJ
	lszhParseDLQState(usHasProt);
#endif

   quint16 bwError = 0;
#ifdef ND_VER_PROGRAM 		// 南都版本 added 2021-12-1
   // quint16 usConnState;  // 并网连接状态   0x1001    1 - 启动(Start Connection);  2 - 成功(Connection Successful);  3 - 结束(Process End)；
    if(2 != KgGlobalData::ms_pStack->usConnState && 3 != KgGlobalData::ms_pStack->usConnState) //  2 - 成功
    {
    	//usHasProt = 1;
    	bwError = 1;
    }
#endif


#ifdef LYGWK_PRJ
	usHasAlarm = isBankAlarm();// 有实时告警时才算有告警，不看总状态0x1111, 0x2222  连云港威控项目-V3.4.7版
#endif
	oldFireAlarm = m_fireAlarm;
	oldThunderAlarm = m_thunderAlarm;
	oldEmergStopAlarm = usEmergStopAlarm;

	QChar fillChar = '0';
	QString strState = QString("%1").arg(m_stackState,4,16,fillChar).toUpper();
	strHint = QString("State:0X%1, HasProt:%2, HasAlarm:%3, ChgFull:%4, DischgEmpty:%5.")
		.arg(strState).arg(usHasProt).arg(usHasAlarm).arg(usChargeFull).arg(usDischargeEmpty);
	sendLog(0, strHint);

	quint16 olDoState = KgGlobalData::ms_dryData.IOCtrl;

	// 要先设置干结点，再控制合闸分闸, 因为分闸有延时

	// ============================step1:设置故障干结点
	for(k = 0; k < KgGlobalData::ms_gzCtrlList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_gzCtrlList[k];
		quint16 usAllProt =  usHasProt | m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm | m_waterAlarm | m_thunderAlarm | usEmergStopAlarm | m_combusGasAlarm;
        //printf("usAllProt===============%d,%d-%d-%d,%d-%d-%d-%d\n",
		//	usAllProt,m_fireAlarm, m_fireFaultAlarm, m_fireSprayAlarm,
		//	m_waterAlarm,m_thunderAlarm,usEmergStopAlarm,m_combusGasAlarm);
		
		/*if(0 == k && 1== KgGlobalData::ms_saveHlkgLog)
		{
			if(usAllProt && !m_usOldHasProt)// added 2021-07-16 
			{
				if(isChLang())
				   saveLogToBaDb(QString("打开故障干结点(DO%1).").arg(stg.doIndex+1));
				else
				   saveLogToBaDb(QString("Open fault dry contact(DO%1).").arg(stg.doIndex+1));
			}
			if(!usAllProt && m_usOldHasProt)
			{
				if(isChLang())
				   saveLogToBaDb(QString("关闭故障干结点(DO%1).").arg(stg.doIndex+1));
				else
				   saveLogToBaDb(QString("Close fault dry contact(DO%1).").arg(stg.doIndex+1));
			}
			// 有故障，打开干节点
			// 无故障，关闭干节点
			m_usOldHasProt = usAllProt; 
		}*/
		setDoState(stg.doIndex,usAllProt); 
	}

    for(k = 0; k < KgGlobalData::ms_bwGzCtrlList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_bwGzCtrlList[k];
		setDoState(stg.doIndex, bwError); 
	}

	// ============================step2:设置运行灯干结点 added 2021-2-26
	for(k = 0; k < KgGlobalData::ms_runCtrlList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_runCtrlList[k];
		if (usHasProt | m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm | m_waterAlarm | m_thunderAlarm | usEmergStopAlarm | m_fuseAlarm | hasCombusGasAlarm()) 
		{
			setDoState(stg.doIndex, 0); // 有故障，关闭运行灯
		}
		else
		{
			setDoState(stg.doIndex, 1); // 无故障，打开运行灯
		}
	}
	
	// ============================step3:设置告警干结点
	for(k = 0; k < KgGlobalData::ms_alarmCtrlList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_alarmCtrlList[k];
		if(0 == k && 1== KgGlobalData::ms_saveHlkgLog)
		{
			if(usHasAlarm && !m_usOldHasAlarm)// added 2021-07-16
			{
				if(isChLang())
				    saveLogToBaDb(kgConvert("打开告警干结点") + QString("(DO%1).").arg(stg.doIndex+1));
				else
					saveLogToBaDb(QString("Open alarm dry contact(DO%1).").arg(stg.doIndex+1));
			}
			if(!usHasAlarm && m_usOldHasAlarm)
			{
				if(isChLang())
				   saveLogToBaDb(kgConvert("关闭告警干结点.") + QString("(DO%1).").arg(stg.doIndex+1));
				else
				   saveLogToBaDb(QString("Close alarm dry contact(DO%1).").arg(stg.doIndex+1));
			}
			// 有告警，打开干节点
			// 无告警，关闭干节点
			m_usOldHasAlarm = usHasAlarm;
		}
		setDoState(stg.doIndex, usHasAlarm);
	}

	int hasOtherAlam = 0;
#ifdef YW0357_PRJ  // added 2022-07-05
    hasOtherAlam = 0;// isBoxVolTempDiffAlarm();
#endif

	// ============================step4:设置禁充干结点
	for(k = 0; k < KgGlobalData::ms_phbChgList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_phbChgList[k];
		setDoState(stg.doIndex, hasOtherAlam | usHasProt | m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm | m_waterAlarm | m_thunderAlarm | usEmergStopAlarm  | m_fuseAlarm | usChargeFull | usProhibitChgDchg |hasCombusGasAlarm());
	}

	// ============================step5:设置禁放干结点
	for(k = 0; k < KgGlobalData::ms_phbDischgList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_phbDischgList[k];
		setDoState(stg.doIndex, hasOtherAlam | usHasProt | m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm | m_waterAlarm | m_thunderAlarm | usEmergStopAlarm  | m_fuseAlarm | usDischargeEmpty | usProhibitChgDchg |hasCombusGasAlarm());
	}

	// ============================step6:设置充电驱动干结点
	for(k = 0; k < KgGlobalData::ms_chgDriveList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_chgDriveList[k];
		if (usHasProt | m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm | m_waterAlarm | m_thunderAlarm | usEmergStopAlarm  | m_fuseAlarm | usChargeFull | usProhibitChgDchg |hasCombusGasAlarm())
		{
			setDoState(stg.doIndex, 0); 
		}
		else
		{
			setDoState(stg.doIndex, 1); 
		}
	}

	// ============================step7:设置放电驱动干结点
	for(k = 0; k < KgGlobalData::ms_dchgDriveList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_dchgDriveList[k];
		if (usHasProt | m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm | m_waterAlarm | m_thunderAlarm | usEmergStopAlarm  | m_fuseAlarm | usDischargeEmpty | usProhibitChgDchg |hasCombusGasAlarm())
		{
			setDoState(stg.doIndex, 0); 
		}
		else
		{
			setDoState(stg.doIndex, 1); 
		}
	}
	
	// ============================step8:设置消防动作干结点
	for(k = 0; k < KgGlobalData::ms_xfStrategy.xfCtrlList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_xfStrategy.xfCtrlList[k];
		setDoState(stg.doIndex, m_fireAlarm | m_fireFaultAlarm | m_fireSprayAlarm /*|m_fireDetectAlarm*/| m_waterAlarm | m_thunderAlarm | hasCombusGasAlarm());
	}
	
    //  ============================step8:设置消防喷洒动作干结点
	for(k = 0; k < KgGlobalData::ms_xfSprayStrategy.xfCtrlList.size(); ++k) // added 2022-12-10
	{
		DOStrategy stg = KgGlobalData::ms_xfSprayStrategy.xfCtrlList[k];
		setDoState(stg.doIndex, m_fireSprayAlarm);
	}

	// ============================step9:设置防雷动作干结点
	for(k = 0; k < KgGlobalData::ms_tdStrategy.xfCtrlList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_tdStrategy.xfCtrlList[k];
		setDoState(stg.doIndex, m_thunderAlarm);
	}

	// ============================step10:设置BMS-EMS通信故障干结点
	for(k = 0; k < KgGlobalData::ms_bmsEmsCommFaultList.size(); ++k)
	{
		DOStrategy stg = KgGlobalData::ms_bmsEmsCommFaultList[k];
		quint16 usCommFault = 0;
#ifdef ND_VER_PROGRAM 	// 南都版本 
        // Bit3: EMS通信故障报警;  Bit2: EMS communication fault alarm; 
		if ((KgGlobalData::ms_pStack->usStackTotAlarm & (1 << 3)) > 0)
		{
			usCommFault = 1;
		}
#endif
		setDoState(stg.doIndex, usCommFault);
	}

	// 合闸口默认是断开的 added 2021-7-20
	for (k = 0; k < KgGlobalData::ms_hlkgStrategy.hzDoList.size(); ++k)
	{
		doIndex = KgGlobalData::ms_hlkgStrategy.hzDoList[k];
		KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
	}
	
	// 分闸口默认是断开的	
	for (k = 0; k < KgGlobalData::ms_hlkgStrategy.fzDoList.size(); ++k)
	{
		doIndex = KgGlobalData::ms_hlkgStrategy.fzDoList[k];
		KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
	}
	
    // 消防脱扣分闸口默认是断开的
	for (k = 0; k < KgGlobalData::ms_hlkgStrategy.xfTkDoList.size(); ++k)
	{
		doIndex = KgGlobalData::ms_hlkgStrategy.xfTkDoList[k];
		KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
	}

	// 消防喷洒脱扣分闸口默认是断开的
	for (k = 0; k < KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList.size(); ++k)
	{
		doIndex = KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList[k];
		KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
	}
	
    // 低电压保护分励脱扣默认是断开的
	for (k = 0; k < KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList.size(); ++k)
	{
		doIndex = KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList[k];
		KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
	}

	/*
    setBankDoState(fireAlarm);
	setDoState(0,usHasProt | fireAlarm);                   //为报警灯
	setDoState(1,usHasProt | fireAlarm | usChargeFull);    //为禁充干结点
	setDoState(2,usHasProt | fireAlarm | usDischargeEmpty);//为禁放干结点
	*/
	
	/*
    //设置故障灯DO3
    setDoState(2, usHasProt | fireAlarm);
   
    //设置排风扇继电器DO4
    setDoState(3, fireAlarm);
   
    //设置空调继电器DO5
    setDoState(4, fireAlarm);
   
    //设置协控DO6
    setDoState(5, usHasProt | fireAlarm);
    */
	//sendLog(0, QString("olDoState:%1, IOCtrl:%2").arg(olDoState).arg((int)KgGlobalData::ms_dryData.IOCtrl));

	//writeKgLogfile(QString("&&&&&&&&&& %1  %2").arg(olDoState).arg(KgGlobalData::ms_dryData.IOCtrl));
	if(olDoState != KgGlobalData::ms_dryData.IOCtrl) // DO状态发生了变化，才下发  || 0 == m_setDoCount
	{
		m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,0);
	}
    m_pIOReader->DealwithSetDoCmd(0,KgGlobalData::ms_dryData); // 执行设置故障灯，运行灯等命令
}

int g_xfSprayCount = 0;
void DryCtrlThread::controlOtherFz()
{
	// modified 2023-3-13
	//if(1 == m_fireAlarm || 1 == m_fireFaultAlarm || 1 == m_fireSprayAlarm || 1 == m_combusGasAlarm || 1 == m_waterAlarm) // 发生了消防告警
	if(1 == m_fireAlarm || 1 == m_fireSprayAlarm || 1 == m_waterAlarm) // 发生了消防告警
	{
		writeKgLogfile(QString("========================== controlOtherFz 888 %1 m_xfTkMotionCount:%2")
			.arg(KgGlobalData::ms_hlkgStrategy.xfTkDoList.size()).arg(m_xfTkMotionCount));
		// 有消防脱扣干节点 added 2021-10-29
		if(KgGlobalData::ms_hlkgStrategy.xfTkDoList.size() > 0 && m_xfTkMotionCount < 3) // 发生消防告警，只执行消防脱扣2次
		{
			++m_xfTkMotionCount;
			
			int doIndex = KgGlobalData::ms_hlkgStrategy.xfTkDoList.at(0);
			openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.xfTkDoList);
			//openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.fzDoList);// added 2022-11-17
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000;
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,delayTime);
			if(0 == m_xfTkMotionLogCount)
			{
				m_xfTkMotionLogCount = 1;
				if(isChLang())
				   saveLogToBaDb(kgConvert("消防告警分励脱扣") + QString("(DO%1).").arg(doIndex+1));
				else
				   saveLogToBaDb(QString("Fire alarm, opening switch(DO%1).").arg(doIndex+1));
			}

			closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.xfTkDoList);
			//closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.fzDoList);// added 2022-11-17
			
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,0);
			m_pIOReader->DealwithSetDoCmd(0,KgGlobalData::ms_dryData);

			if(KgGlobalData::ms_hlkgStrategy.fzDoList.size() > 0) // added 2022-11-17
			{
				m_drvFzSuccedCount += 1;
			}
		}
	}
	else
	{
		m_xfTkMotionCount = 0;
		m_xfTkMotionLogCount = 0;
	}
      
	if(1 == m_fireSprayAlarm) // 发生了消防喷洒告警 // added 2022-12-10
	{
		writeKgLogfile(QString("========================== controlOtherFz 889 %1 m_xfSprayTkMotionCount:%2")
			.arg(KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList.size()).arg(m_xfSprayTkMotionCount));
		if(g_xfSprayCount < 1000)
		{
			g_xfSprayCount += 1;
		}
		// 有消防喷洒脱扣干节点
		if(g_xfSprayCount >= 15 && KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList.size() > 0 && m_xfSprayTkMotionCount < 3) // 发生消防喷洒脱告警，只执行脱扣2次
		{
			++m_xfSprayTkMotionCount;
			
			int doIndex = KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList.at(0);
			openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList);// 先闭合
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000;
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,delayTime);
			if(0 == m_xfSprayTkMotionLogCount)
			{
				m_xfSprayTkMotionLogCount = 1;
				if(isChLang())
				   saveLogToBaDb(kgConvert("消防喷洒分励脱扣") + QString("(DO%1).").arg(doIndex+1));
				else
				   saveLogToBaDb(QString("Fire spray alarm, opening switch(DO%1).").arg(doIndex+1));
			}
            closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.xfSprayTkDoList);// 再断开
			
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,0);
			m_pIOReader->DealwithSetDoCmd(0,KgGlobalData::ms_dryData);

			if(KgGlobalData::ms_hlkgStrategy.fzDoList.size() > 0) // added 2022-11-17
			{
				m_drvFzSuccedCount += 1;
			}
		}
	}
	else
	{
		m_xfSprayTkMotionCount = 0;
		m_xfSprayTkMotionLogCount = 0;
		g_xfSprayCount = 0;
	}

	bool isVolDownProt = hasVolDownPort();
	if(isVolDownProt)
	{
		if (KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList.size() > 0 && m_volDownProtTkCount < 3)
		{
			m_volDownProtTkCount += 1;
			int doIndex = KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList.at(0);
			openDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList);// 先闭合
			int delayTime = KgGlobalData::ms_tkDelayTime * 1000;
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,delayTime);
			if(0 == m_volDownProtTkLogCount)
			{
				m_volDownProtTkLogCount = 1;
				
				if(isChLang())
				   saveLogToBaDb(kgConvert("低电压保护分励脱扣") + QString("(DO%1).").arg(doIndex+1));
				else
				   saveLogToBaDb(QString("Vol down protect, opening switch(DO%1).").arg(doIndex+1));
			}

			closeDos(KgGlobalData::ms_dryData.IOCtrl, KgGlobalData::ms_hlkgStrategy.volDownProtFzDoList);// 再断开
			m_pIOReader->AddSetCmd(0,KgGlobalData::ms_dryData.IOCtrl,0);
			m_pIOReader->DealwithSetDoCmd(0,KgGlobalData::ms_dryData);

			if(KgGlobalData::ms_hlkgStrategy.fzDoList.size() > 0) // added 2022-11-17
			{
				m_drvFzSuccedCount += 1;
			}
		 }
	}
    else
	{
		m_volDownProtTkCount = 0;
		m_volDownProtTkLogCount = 0;
	}
}

//控制DO口是否闭合(打开继电器)
bool DryCtrlThread::setDoState(quint16 doIndex, quint16 usSetVal)
{
	/*
	操作DO  打开第1个继电器
	发送:FE 05 00 00 FF 00 98 35 
	接收:FE 05 00 00 FF 00 98 35 
	*/
	unsigned short cmd = 0;
	QString strLog;
	//msleep(50);//msleep(300);

    if (usSetVal)//需要打开
    {
		//strLog = QString("==================usSetVal:%1, set DO%2 to open").arg(usSetVal).arg(doIndex+1);
		strLog = QString("UsSetVal:%1, set DO%2 to open.").arg(usSetVal).arg(doIndex+1);
		sendLog(0, strLog);
		//g_DOState |= (1 << doIndex);
		KgGlobalData::ms_dryData.IOCtrl |= (1 << doIndex);
    }
	else
	{
	    //strLog = QString("==================usSetVal:%1, set DO%2 to close").arg(usSetVal).arg(doIndex+1);
	    strLog = QString("UsSetVal:%1, set DO%2 to close.").arg(usSetVal).arg(doIndex+1);
		sendLog(0, strLog);
		//g_DOState &= ~(1 << doIndex);
		KgGlobalData::ms_dryData.IOCtrl &= ~(1 << doIndex);
	}
	
	return true;////////////////////////////

	/*
    sendCtrlDoCmd(doIndex, usSetVal);
	
	int iRetVal = readDevReplay(doIndex+1, 8);
	if (iRetVal >= 8)
	{
		//
		//iRetVal = analySetSingleDatagram(m_devAddr, m_pDataBuf, iRetVal, doIndex, cmd);
		//if (0 != iRetVal)
		//{
		//   sendLog(RUN_LOG_FAILED_DEV, QString("analyRtuDatagram ret:%1").arg(iRetVal));
		//}
		//return iRetVal;
		g_connFailedCount = 0;
	}
	else
	{
	   iRetVal = -2;
	   if (g_connFailedCount < 50000)
		{
			g_connFailedCount += 1;
		}
	}

	return iRetVal;	
	*/
}

void DryCtrlThread::readDIValue(quint16 runCount)
{
	int ret = readDevDIState(KgGlobalData::ms_pStack, KgGlobalData::ms_dryData.failedCount); 
	
	// 刚检测到有消防信号，或防雷信号，或急停信号,但还没报警, 再读一次进行确认 // added 2021-3-25
	if ((m_fireCount > 0 && m_fireCount < KgGlobalData::ms_xfStrategy.confirmedCount) || 
 		(m_thunderCount > 0 && m_thunderCount < KgGlobalData::ms_tdStrategy.confirmedCount) || 
 		(m_emergStopCount > 0 && m_emergStopCount < KgGlobalData::ms_emgStopStrategy.confirmedCount) ||
		(m_fuseCount > 0 && m_fuseCount < KgGlobalData::ms_fuseStrategy.confirmedCount))
	{
	    this->msleep(500);//200
		ret = readDevDIState(KgGlobalData::ms_pStack, KgGlobalData::ms_dryData.failedCount);
	}
	
	dealwithConnFailed(runCount);

	QString strHint = QString("DIState:%1, DOState:%2, drvFzCnt:%3, drvHzCnt:%4")
		.arg(KgGlobalData::ms_dryData.DIVal).arg(KgGlobalData::ms_dryData.IOCtrl).arg(m_drvFzCount).arg(m_drvHzCount);
	//if (KgGlobalData::ms_hlkgStrategy.diCfg.diIndex < KgGlobalData::ms_devDiCount) // 有采集汇流开关反馈
	if(KgGlobalData::ms_hlkgStrategy.diCfgList.size() > 0)
	{
		strHint += QString(", hlkgState:%1.").arg(getConfSwitchStrState());
	}
	sendLog(0, strHint);

	strHint = QString("***FireAlarm:%1-%2-%3, thunderAlarm:%4-%5-%6, emergStopAlarm:%7-%8-%9.")
	 	.arg(KgGlobalData::ms_xfStrategy.diList.size()).arg(m_fireCount).arg(m_fireAlarm)
	 	.arg(KgGlobalData::ms_tdStrategy.diList.size()).arg(m_thunderCount).arg(m_thunderAlarm)
	 	.arg(KgGlobalData::ms_emgStopStrategy.diList.size()).arg(m_emergStopCount).arg(m_emergStopAlarm);
	sendLog(0, strHint); 

	if(KgGlobalData::ms_dryData.readDiCount > 0)
	{
	    SetBamsFireAlarm(m_fireFaultAlarm | m_fireAlarm | m_fireSprayAlarm | hasCombusGasAlarm());
		SetBamsWaterAlarm(m_waterAlarm);
		SetFuseAlarm(m_fuseAlarm); // deleted 2022-11-16
		//SetBamsFireAlarm(m_waterAlarm); // 华电新乡，水浸当做消防处理 2021-12-1
	}
}

//printf("pStack->usDI2================%d\n", pStack->usDI2);

/* test 2020-9-27
sendLog(RUN_LOG_FAILED_DEV, QString("usConfSwitchStrategy:%1").arg(pStack->usConfSwitchStrategy));
if (200 ==pStack->usConfSwitchStrategy)// 汇流开关策略 200 - 3rd进程设定 汇流开关断开,才能闭合接触器
	{
    pStack->usConfSwitchState = 0;//通知BA 汇流开关已经闭合
    sendLog(RUN_LOG_FAILED_DEV, "pStack->usConfSwitchState = 1");
}*/

/*if (++test ==1)
{
    // QString strLog = "EMS control confluence switch closing";
    // QString strLog = "EMS control confluence switch opening";
    // QString strLog = "EMS 控制汇流开关合闸";
	saveLogToBaDb(EMS_CTRL_SWITCH_CLOSE_STR);
}*/

// 2022-3-30测试 616ms循环一次 DryCtrl/XfConfirmedCount配置为6时，从检测到消防信号，到报消防告警大约需3秒
void DryCtrlThread::run()
{
    int ret = 0;
	quint16 runCount = 0;
	QString strHint;
	DryData &m_Para = KgGlobalData::ms_dryData;
	
	sleep(1);//程序刚启动时，本程序晚一点运行 
	//m_pRtuClient = new CXnSerial;// Client
	
	/*
	CBattStack *pStack = KgGlobalData::ms_pRTDB->getStack(0);
	if (0 == pStack)
	{
	   printf("pStack is null\n");
	   return;
	}
	*/
    writeKgLogfile(QString("step500"));
	
	while(1)
	{
	    msleep(500);//msleep(10);
		if (runCount < 100)
		{
			runCount += 1;
		}
		
		writeKgLogfile(QString("step101"));
		printDiDoState();

		getInstallInfo();

		CBattStack *pStack = KgGlobalData::ms_pRTDB->getStack(0);
		if (pStack)
		{
		   //pStack->fStackVol = 632;
		   //pStack->fStackCur = -12.3;
		   //pStack->usDI3 = 1;
		   //pStack->usDI4 = 1;
		   //msleep(2000);
		   //continue; // testing 

		   writeKgLogfile(QString("==================usDI4:%1.").arg(pStack->usDI4));
		}
		
        /*  testing for YW-PF0318
		KgGlobalData::ms_pStack->aExIOModuConnFault = 0;  // added 2022-5-22
		SetEmergeStopAlarm(0); //
		writeKgLogfile(QString("==================Moni emergency over."));
		this->msleep(2000);
		continue;
		*/
		
		if(0 == KgGlobalData::ms_pStack)
		{
			printf("pStack is null.\n");
			this->msleep(2000);
			continue;
		}

        // writeKgLogfile(QString("step501"));

		/*if(!m_pIOReader->openSerialPort())
		{
			this->msleep(5000);
			continue;
		}*/
		
        // 第1帧：读取DO状态=========================================================1 Read DO
		//readDevDOState();  
		m_pIOReader->readDevDOState(0, KgGlobalData::ms_dryData);
		// writeKgLogfile(QString("step502"));
		
		// 第2帧：根据工况设置DO (如果状态没有改变，则不下发)========================2 Set DO
		setSomeDOState();

		controlHzFz();   // 控制汇流开关，此处有延时，所以要单独分开执行
	  
		controlOtherFz();// 控制其他脱扣

		// writeKgLogfile(QString("step503"));
		// 第3帧：读取DI状态并判断消防告警===========================================3 Read DI
		msleep(50);
		readDIValue(runCount);
		
#ifdef HAS_SECOND_IO_DEV
		// 读取第二个IO模块的DI数据 // added 2022-8-2
		int oldDIVal = KgGlobalData::ms_drySecData.DIVal;
		m_pIOReader->readDevDIState(1, KgGlobalData::ms_drySecData);//查询成功
		if(oldDIVal != KgGlobalData::ms_drySecData.DIVal)
		{
			 this->msleep(500);
			 m_pIOReader->readDevDIState(1, KgGlobalData::ms_drySecData);//查询成功
		}
#endif	
		if (runCount >= 1)
		{
			updateDryDataToRtdb(this);    //更新DI1-4数据到BA的通用保持寄存器50-53中 2020-1-15
		}
	}
}
